- Timestamp:
- Jun 10, 2017 10:38:40 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/isomaker.cpp
r67328 r67330 45 45 #include <iprt/string.h> 46 46 #include <iprt/vfs.h> 47 #include <iprt/vfslowlevel.h> 47 48 #include <iprt/formats/iso9660.h> 48 49 … … 199 200 * This is for Rock Ridge. */ 200 201 RTDEV Device; 202 /** The inode/serial number. 203 * This is for Rock Ridge. */ 204 uint64_t INode; 201 205 /** The number of hardlinks to report in the file stats. 202 206 * This is for Rock Ridge. */ 203 207 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; 208 211 /** The offset of the directory entry in the parent directory. */ 209 212 uint32_t offDirRec; … … 497 500 498 501 502 /** 503 * Instance data of an ISO maker output file. 504 */ 505 typedef 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. */ 513 typedef RTFSISOMAKEROUTPUTFILE *PRTFSISOMAKEROUTPUTFILE; 514 515 516 499 517 /********************************************************************************************************************************* 500 518 * Structures and Typedefs * … … 579 597 PRTFSISOMAKERFILE *ppFile); 580 598 static int rtFsIsoMakerObjRemoveWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj); 599 600 static DECLCALLBACK(int) rtFsIsoMakerOutFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual); 581 601 582 602 … … 1731 1751 pName->gid = pObj->gid; 1732 1752 pName->Device = 0; 1753 pName->INode = pObj->idxObj; 1733 1754 pName->cHardlinks = 1; 1734 pName-> INode = pObj->idxObj;1755 pName->offTransTbl = UINT32_MAX; 1735 1756 pName->offDirRec = UINT32_MAX; 1736 1757 pName->cbDirRec = 0; … … 2788 2809 */ 2789 2810 static 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. */ 2794 2819 size_t cbDirRec = RT_UOFFSETOF(ISO9660DIRREC, achFileId) + pName->cbNameInDirRec + !(pName->cbNameInDirRec & 1); 2795 2820 AssertReturn(cbDirRec <= UINT8_MAX, VERR_FILENAME_TOO_LONG); 2796 2821 pName->cbDirRec = (uint8_t)cbDirRec; 2797 2822 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 */ 2799 2827 if (pFinalizedDirs->pRRSpillFile) 2800 2828 { 2829 /** @todo rock ridge */ 2801 2830 RT_NOREF(uRootRockRidge); 2802 2831 } … … 2824 2853 2825 2854 /* 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. 2827 2858 */ 2828 2859 if (pFinalizedDirs->pRRSpillFile) … … 2831 2862 pFinalizedDirs->pRRSpillFile = NULL; 2832 2863 } 2833 if (pNamespace->fNamespace) 2834 { 2864 if (pNamespace->uRockRidgeLevel > 0) 2865 { 2866 /** @todo create rock ridge spill file to indicate rock ridge */ 2835 2867 } 2836 2868 … … 2843 2875 * Precalc the directory record size for the root directory. 2844 2876 */ 2845 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/, true /*fIsRoot*/); 2877 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/, 0 /*offInTransTbl*/, 2878 pNamespace->uRockRidgeLevel); 2846 2879 AssertRCReturn(rc, rc); 2847 2880 … … 2863 2896 2864 2897 /* 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; 2868 2901 while (cLeft-- > 0) 2869 2902 { 2870 2903 PRTFSISOMAKERNAME pChild = *ppChild++; 2871 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir, false /*fIsRoot*/);2904 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir, offInTransTbl, 0 /*uRootRockRidge*/); 2872 2905 AssertRCReturn(rc, rc); 2873 2906 2874 2907 offInDir += pChild->cbDirRec; 2875 2908 if (pChild->cchTransNm) 2876 cbTransTbl += 2 /* type & space*/2877 +RT_MAX(pChild->cchName, 39)2878 +1 /* tab */2879 +pChild->cchTransNm2880 +1 /* newline */;2909 offInTransTbl += 2 /* type & space*/ 2910 + RT_MAX(pChild->cchName, 39) 2911 + 1 /* tab */ 2912 + pChild->cchTransNm 2913 + 1 /* newline */; 2881 2914 } 2882 2915 … … 2888 2921 /* Set the translation table file size. */ 2889 2922 if (pCurDir->pTransTblFile) 2890 pCurDir->pTransTblFile->cbData = cbTransTbl;2923 pCurDir->pTransTblFile->cbData = offInTransTbl; 2891 2924 2892 2925 /* Add to the path table size calculation. */ … … 3404 3437 3405 3438 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 */ 3453 static 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 */ 3467 static 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 */ 3523 static 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 */ 3545 static 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 */ 3555 static 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 */ 3565 static 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 */ 3576 static 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 */ 3587 static 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 */ 3597 static 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 */ 3607 static 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 */ 3618 static 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 */ 3628 static 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 */ 3681 static 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 */ 3692 DECL_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 */ 3742 RTDECL(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.