VirtualBox

Changeset 67330 in vbox for trunk/src


Ignore:
Timestamp:
Jun 10, 2017 10:38:40 AM (8 years ago)
Author:
vboxsync
Message:

IPRT: More ISO maker code.

File:
1 edited

Legend:

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

    r67328 r67330  
    4545#include <iprt/string.h>
    4646#include <iprt/vfs.h>
     47#include <iprt/vfslowlevel.h>
    4748#include <iprt/formats/iso9660.h>
    4849
     
    199200     * This is for Rock Ridge.  */
    200201    RTDEV                   Device;
     202    /** The inode/serial number.
     203     * This is for Rock Ridge.  */
     204    uint64_t                INode;
    201205    /** The number of hardlinks to report in the file stats.
    202206     * This is for Rock Ridge.  */
    203207    uint32_t                cHardlinks;
    204     /** The inode/serial number.
    205      * This is for Rock Ridge.  */
    206     uint64_t                INode;
    207 
     208
     209    /** The offset of the translate table file entry. */
     210    uint32_t                offTransTbl;
    208211    /** The offset of the directory entry in the parent directory. */
    209212    uint32_t                offDirRec;
     
    497500
    498501
     502/**
     503 * Instance data of an ISO maker output file.
     504 */
     505typedef struct RTFSISOMAKEROUTPUTFILE
     506{
     507    /** The ISO maker (owns a reference). */
     508    PRTFSISOMAKERINT        pIsoMaker;
     509    /** The current file position. */
     510    uint64_t                offCurPos;
     511} RTFSISOMAKEROUTPUTFILE;
     512/** Pointer to the instance data of an ISO maker output file. */
     513typedef RTFSISOMAKEROUTPUTFILE *PRTFSISOMAKEROUTPUTFILE;
     514
     515
     516
    499517/*********************************************************************************************************************************
    500518*   Structures and Typedefs                                                                                                      *
     
    579597                                            PRTFSISOMAKERFILE *ppFile);
    580598static int rtFsIsoMakerObjRemoveWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj);
     599
     600static DECLCALLBACK(int) rtFsIsoMakerOutFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual);
    581601
    582602
     
    17311751            pName->gid                  = pObj->gid;
    17321752            pName->Device               = 0;
     1753            pName->INode                = pObj->idxObj;
    17331754            pName->cHardlinks           = 1;
    1734             pName->INode                = pObj->idxObj;
     1755            pName->offTransTbl          = UINT32_MAX;
    17351756            pName->offDirRec            = UINT32_MAX;
    17361757            pName->cbDirRec             = 0;
     
    27882809 */
    27892810static int rtFsIsoMakerFinalizeIsoDirectoryEntry(PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs, PRTFSISOMAKERNAME pName,
    2790                                                  uint32_t offInDir, uint8_t uRootRockRidge)
    2791 {
    2792     pName->offDirRec = offInDir;
    2793 
     2811                                                 uint32_t offInDir, uint32_t offInTransTbl, uint8_t uRootRockRidge)
     2812{
     2813    /* Set directory and translation table offsets.  (These are for
     2814       helping generating data blocks later.) */
     2815    pName->offDirRec   = offInDir;
     2816    pName->offTransTbl = offInTransTbl;
     2817
     2818    /* Calculate the minimal directory record size. */
    27942819    size_t cbDirRec  = RT_UOFFSETOF(ISO9660DIRREC, achFileId) + pName->cbNameInDirRec + !(pName->cbNameInDirRec & 1);
    27952820    AssertReturn(cbDirRec <= UINT8_MAX, VERR_FILENAME_TOO_LONG);
    27962821    pName->cbDirRec  = (uint8_t)cbDirRec;
    27972822
    2798     /** @todo rock ridge    */
     2823    /*
     2824     * Calculate additional rock ridge stuff, if it doesn't all fit write it
     2825     * to the spill file.
     2826     */
    27992827    if (pFinalizedDirs->pRRSpillFile)
    28002828    {
     2829        /** @todo rock ridge    */
    28012830        RT_NOREF(uRootRockRidge);
    28022831    }
     
    28242853
    28252854    /*
    2826      * Reset the rock ridge spill file, in case we someone are finalized multiple times.
     2855     * Reset the rock ridge spill file (in case we allow finalizing more than once)
     2856     * and create a new spill file if rock ridge is enabled.  The directory entry
     2857     * finalize function uses this as a clue that rock ridge is enabled.
    28272858     */
    28282859    if (pFinalizedDirs->pRRSpillFile)
     
    28312862        pFinalizedDirs->pRRSpillFile = NULL;
    28322863    }
    2833     if (pNamespace->fNamespace)
    2834     {
     2864    if (pNamespace->uRockRidgeLevel > 0)
     2865    {
     2866        /** @todo create rock ridge spill file to indicate rock ridge */
    28352867    }
    28362868
     
    28432875         * Precalc the directory record size for the root directory.
    28442876         */
    2845         rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/, true /*fIsRoot*/);
     2877        rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/, 0 /*offInTransTbl*/,
     2878                                                   pNamespace->uRockRidgeLevel);
    28462879        AssertRCReturn(rc, rc);
    28472880
     
    28632896
    28642897            /* Finalize the directory entries. */
    2865             uint32_t            cbTransTbl = 0;
    2866             uint32_t            cLeft      = pCurDir->cChildren;
    2867             PPRTFSISOMAKERNAME  ppChild    = pCurDir->papChildren;
     2898            uint32_t            offInTransTbl = 0;
     2899            uint32_t            cLeft         = pCurDir->cChildren;
     2900            PPRTFSISOMAKERNAME  ppChild       = pCurDir->papChildren;
    28682901            while (cLeft-- > 0)
    28692902            {
    28702903                PRTFSISOMAKERNAME pChild = *ppChild++;
    2871                 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir, false /*fIsRoot*/);
     2904                rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir, offInTransTbl, 0 /*uRootRockRidge*/);
    28722905                AssertRCReturn(rc, rc);
    28732906
    28742907                offInDir += pChild->cbDirRec;
    28752908                if (pChild->cchTransNm)
    2876                     cbTransTbl += 2 /* type & space*/
    2877                                 + RT_MAX(pChild->cchName, 39)
    2878                                 + 1 /* tab */
    2879                                 + pChild->cchTransNm
    2880                                 + 1 /* newline */;
     2909                    offInTransTbl += 2 /* type & space*/
     2910                                  + RT_MAX(pChild->cchName, 39)
     2911                                  + 1 /* tab */
     2912                                  + pChild->cchTransNm
     2913                                  + 1 /* newline */;
    28812914            }
    28822915
     
    28882921            /* Set the translation table file size. */
    28892922            if (pCurDir->pTransTblFile)
    2890                 pCurDir->pTransTblFile->cbData = cbTransTbl;
     2923                pCurDir->pTransTblFile->cbData = offInTransTbl;
    28912924
    28922925            /* Add to the path table size calculation. */
     
    34043437
    34053438
     3439
     3440
     3441
     3442/*
     3443 *
     3444 * Image I/O.
     3445 * Image I/O.
     3446 * Image I/O.
     3447 *
     3448 */
     3449
     3450/**
     3451 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
     3452 */
     3453static DECLCALLBACK(int) rtFsIsoMakerOutFile_Close(void *pvThis)
     3454{
     3455    PRTFSISOMAKEROUTPUTFILE pThis = (PRTFSISOMAKEROUTPUTFILE)pvThis;
     3456
     3457    RTFsIsoMakerRelease(pThis->pIsoMaker);
     3458    pThis->pIsoMaker = NULL;
     3459
     3460    return VINF_SUCCESS;
     3461}
     3462
     3463
     3464/**
     3465 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     3466 */
     3467static DECLCALLBACK(int) rtFsIsoMakerOutFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     3468{
     3469    PRTFSISOMAKEROUTPUTFILE pThis     = (PRTFSISOMAKEROUTPUTFILE)pvThis;
     3470    PRTFSISOMAKERINT        pIsoMaker = pThis->pIsoMaker;
     3471
     3472
     3473    pObjInfo->cbObject         = pIsoMaker->cbFinalizedImage;
     3474    pObjInfo->cbAllocated      = pIsoMaker->cbFinalizedImage;
     3475    pObjInfo->AccessTime       = pIsoMaker->ImageCreationTime;
     3476    pObjInfo->ModificationTime = pIsoMaker->ImageCreationTime;
     3477    pObjInfo->ChangeTime       = pIsoMaker->ImageCreationTime;
     3478    pObjInfo->BirthTime        = pIsoMaker->ImageCreationTime;
     3479    pObjInfo->Attr.fMode       = 0444 | RTFS_TYPE_FILE | RTFS_DOS_READONLY;
     3480
     3481    switch (enmAddAttr)
     3482    {
     3483        case RTFSOBJATTRADD_NOTHING:
     3484            enmAddAttr = RTFSOBJATTRADD_UNIX;
     3485            /* fall thru */
     3486        case RTFSOBJATTRADD_UNIX:
     3487            pObjInfo->Attr.u.Unix.uid           = NIL_RTUID;
     3488            pObjInfo->Attr.u.Unix.gid           = NIL_RTGID;
     3489            pObjInfo->Attr.u.Unix.cHardlinks    = 1;
     3490            pObjInfo->Attr.u.Unix.INodeIdDevice = 0;
     3491            pObjInfo->Attr.u.Unix.INodeId       = 0;
     3492            pObjInfo->Attr.u.Unix.fFlags        = 0;
     3493            pObjInfo->Attr.u.Unix.GenerationId  = 0;
     3494            pObjInfo->Attr.u.Unix.Device        = 0;
     3495            break;
     3496
     3497        case RTFSOBJATTRADD_UNIX_OWNER:
     3498            pObjInfo->Attr.u.UnixOwner.uid = NIL_RTUID;
     3499            pObjInfo->Attr.u.UnixOwner.szName[0] = '\0';
     3500            break;
     3501
     3502        case RTFSOBJATTRADD_UNIX_GROUP:
     3503            pObjInfo->Attr.u.UnixGroup.gid = NIL_RTGID;
     3504            pObjInfo->Attr.u.UnixGroup.szName[0] = '\0';
     3505            break;
     3506
     3507        case RTFSOBJATTRADD_EASIZE:
     3508            pObjInfo->Attr.u.EASize.cb = 0;
     3509            break;
     3510
     3511        default:
     3512            AssertFailedReturn(VERR_INVALID_PARAMETER);
     3513    }
     3514    pObjInfo->Attr.enmAdditional = enmAddAttr;
     3515
     3516    return VINF_SUCCESS;
     3517}
     3518
     3519
     3520/**
     3521 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
     3522 */
     3523static DECLCALLBACK(int) rtFsIsoMakerOutFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
     3524{
     3525    PRTFSISOMAKEROUTPUTFILE pThis     = (PRTFSISOMAKEROUTPUTFILE)pvThis;
     3526    PRTFSISOMAKERINT        pIsoMaker = pThis->pIsoMaker;
     3527    size_t                  cbBuf     = pSgBuf->paSegs[0].cbSeg;
     3528    uint8_t                *pbBuf     = (uint8_t *)pSgBuf->paSegs[0].pvSeg;
     3529    size_t                  cbRead    = 0;
     3530    int                     rc;
     3531    Assert(pSgBuf->cSegs == 1);
     3532
     3533    rc = VERR_NOT_IMPLEMENTED;
     3534    RT_NOREF(pThis, pIsoMaker, cbBuf, pbBuf, off, fBlocking);
     3535
     3536    if (pcbRead)
     3537        *pcbRead = cbRead;
     3538    return rc;
     3539}
     3540
     3541
     3542/**
     3543 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
     3544 */
     3545static DECLCALLBACK(int) rtFsIsoMakerOutFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
     3546{
     3547    RT_NOREF(pvThis, off, pSgBuf, fBlocking, pcbWritten);
     3548    return VERR_WRITE_PROTECT;
     3549}
     3550
     3551
     3552/**
     3553 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
     3554 */
     3555static DECLCALLBACK(int) rtFsIsoMakerOutFile_Flush(void *pvThis)
     3556{
     3557    RT_NOREF(pvThis);
     3558    return VINF_SUCCESS;
     3559}
     3560
     3561
     3562/**
     3563 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
     3564 */
     3565static DECLCALLBACK(int) rtFsIsoMakerOutFile_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
     3566                                              uint32_t *pfRetEvents)
     3567{
     3568    NOREF(pvThis);
     3569    return RTVfsUtilDummyPollOne(fEvents, cMillies, fIntr, pfRetEvents);
     3570}
     3571
     3572
     3573/**
     3574 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
     3575 */
     3576static DECLCALLBACK(int) rtFsIsoMakerOutFile_Tell(void *pvThis, PRTFOFF poffActual)
     3577{
     3578    PRTFSISOMAKEROUTPUTFILE pThis = (PRTFSISOMAKEROUTPUTFILE)pvThis;
     3579    *poffActual = pThis->offCurPos;
     3580    return VINF_SUCCESS;
     3581}
     3582
     3583
     3584/**
     3585 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnSkip}
     3586 */
     3587static DECLCALLBACK(int) rtFsIsoMakerOutFile_Skip(void *pvThis, RTFOFF cb)
     3588{
     3589    RTFOFF offIgnored;
     3590    return rtFsIsoMakerOutFile_Seek(pvThis, cb, RTFILE_SEEK_CURRENT, &offIgnored);
     3591}
     3592
     3593
     3594/**
     3595 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
     3596 */
     3597static DECLCALLBACK(int) rtFsIsoMakerOutFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
     3598{
     3599    RT_NOREF(pvThis, fMode, fMask);
     3600    return VERR_WRITE_PROTECT;
     3601}
     3602
     3603
     3604/**
     3605 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
     3606 */
     3607static DECLCALLBACK(int) rtFsIsoMakerOutFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     3608                                               PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
     3609{
     3610    RT_NOREF(pvThis, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
     3611    return VERR_WRITE_PROTECT;
     3612}
     3613
     3614
     3615/**
     3616 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
     3617 */
     3618static DECLCALLBACK(int) rtFsIsoMakerOutFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
     3619{
     3620    RT_NOREF(pvThis, uid, gid);
     3621    return VERR_WRITE_PROTECT;
     3622}
     3623
     3624
     3625/**
     3626 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
     3627 */
     3628static DECLCALLBACK(int) rtFsIsoMakerOutFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
     3629{
     3630    PRTFSISOMAKEROUTPUTFILE pThis = (PRTFSISOMAKEROUTPUTFILE)pvThis;
     3631
     3632    /*
     3633     * Seek relative to which position.
     3634     */
     3635    uint64_t offWrt;
     3636    switch (uMethod)
     3637    {
     3638        case RTFILE_SEEK_BEGIN:
     3639            offWrt = 0;
     3640            break;
     3641
     3642        case RTFILE_SEEK_CURRENT:
     3643            offWrt = pThis->offCurPos;
     3644            break;
     3645
     3646        case RTFILE_SEEK_END:
     3647            offWrt = pThis->pIsoMaker->cbFinalizedImage;
     3648            break;
     3649
     3650        default:
     3651            return VERR_INTERNAL_ERROR_5;
     3652    }
     3653
     3654    /*
     3655     * Calc new position, take care to stay within RTFOFF type bounds.
     3656     */
     3657    uint64_t offNew;
     3658    if (offSeek == 0)
     3659        offNew = offWrt;
     3660    else if (offSeek > 0)
     3661    {
     3662        offNew = offWrt + offSeek;
     3663        if (   offNew < offWrt
     3664            || offNew > RTFOFF_MAX)
     3665            offNew = RTFOFF_MAX;
     3666    }
     3667    else if ((uint64_t)-offSeek < offWrt)
     3668        offNew = offWrt + offSeek;
     3669    else
     3670        offNew = 0;
     3671    pThis->offCurPos = offNew;
     3672
     3673    *poffActual = offNew;
     3674    return VINF_SUCCESS;
     3675}
     3676
     3677
     3678/**
     3679 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
     3680 */
     3681static DECLCALLBACK(int) rtFsIsoMakerOutFile_QuerySize(void *pvThis, uint64_t *pcbFile)
     3682{
     3683    PRTFSISOMAKEROUTPUTFILE pThis = (PRTFSISOMAKEROUTPUTFILE)pvThis;
     3684    *pcbFile = pThis->pIsoMaker->cbFinalizedImage;
     3685    return VINF_SUCCESS;
     3686}
     3687
     3688
     3689/**
     3690 * Standard file operations.
     3691 */
     3692DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_rtFsIsoMakerOutputFileOps =
     3693{
     3694    { /* Stream */
     3695        { /* Obj */
     3696            RTVFSOBJOPS_VERSION,
     3697            RTVFSOBJTYPE_FILE,
     3698            "ISO Maker Output File",
     3699            rtFsIsoMakerOutFile_Close,
     3700            rtFsIsoMakerOutFile_QueryInfo,
     3701            RTVFSOBJOPS_VERSION
     3702        },
     3703        RTVFSIOSTREAMOPS_VERSION,
     3704        RTVFSIOSTREAMOPS_FEAT_NO_SG,
     3705        rtFsIsoMakerOutFile_Read,
     3706        rtFsIsoMakerOutFile_Write,
     3707        rtFsIsoMakerOutFile_Flush,
     3708        rtFsIsoMakerOutFile_PollOne,
     3709        rtFsIsoMakerOutFile_Tell,
     3710        rtFsIsoMakerOutFile_Skip,
     3711        NULL /*ZeroFill*/,
     3712        RTVFSIOSTREAMOPS_VERSION,
     3713    },
     3714    RTVFSFILEOPS_VERSION,
     3715    0,
     3716    { /* ObjSet */
     3717        RTVFSOBJSETOPS_VERSION,
     3718        RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
     3719        rtFsIsoMakerOutFile_SetMode,
     3720        rtFsIsoMakerOutFile_SetTimes,
     3721        rtFsIsoMakerOutFile_SetOwner,
     3722        RTVFSOBJSETOPS_VERSION
     3723    },
     3724    rtFsIsoMakerOutFile_Seek,
     3725    rtFsIsoMakerOutFile_QuerySize,
     3726    RTVFSFILEOPS_VERSION
     3727};
     3728
     3729
     3730
     3731/**
     3732 * Creates a VFS file for a finalized ISO maker instanced.
     3733 *
     3734 * The file can be used to access the image.  Both sequential and random access
     3735 * are supported, so that this could in theory be hooked up to a CD/DVD-ROM
     3736 * drive emulation and used as a virtual ISO image.
     3737 *
     3738 * @returns IRPT status code.
     3739 * @param   hIsoMaker           The ISO maker handle.
     3740 * @param   phVfsFile           Where to return the handle.
     3741 */
     3742RTDECL(int) RTFsIsoMakerCreateVfsOutputFile(RTFSISOMAKER hIsoMaker, PRTVFSFILE phVfsFile)
     3743{
     3744    PRTFSISOMAKERINT pThis = hIsoMaker;
     3745    RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     3746    AssertReturn(pThis->fFinalized, VERR_WRONG_ORDER);
     3747    AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER);
     3748
     3749    uint32_t cRefs = RTFsIsoMakerRetain(pThis);
     3750    AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
     3751
     3752    PRTFSISOMAKEROUTPUTFILE pFileData;
     3753    RTVFSFILE               hVfsFile;
     3754    int rc = RTVfsNewFile(&g_rtFsIsoMakerOutputFileOps, sizeof(*pFileData), RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_CREATE,
     3755                          NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pFileData);
     3756    if (RT_SUCCESS(rc))
     3757    {
     3758        pFileData->pIsoMaker = pThis;
     3759        pFileData->offCurPos = 0;
     3760        return VINF_SUCCESS;
     3761    }
     3762
     3763    RTFsIsoMakerRelease(pThis);
     3764    *phVfsFile = NIL_RTVFSFILE;
     3765    return rc;
     3766}
     3767
Note: See TracChangeset for help on using the changeset viewer.

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