VirtualBox

儲存庫 vbox 的更動 67571


忽略:
時間撮記:
2017-6-22 下午08:04:26 (7 年 以前)
作者:
vboxsync
訊息:

IPRT: More ISO maker code (import + multi-extent related).

位置:
trunk
檔案:
修改 2 筆資料

圖例:

未更動
新增
刪除
  • trunk/include/iprt/err.h

    r67538 r67571  
    27422742/** Import ISO contains a bad directory record. */
    27432743#define VERR_ISOMK_IMPORT_BAD_DIR_REC                   (-25124)
    2744 /** Import ISO directory record with a mismatching volume sequence number. */
     2744/** Import ISO contains a directory record with a mismatching volume sequence
     2745 *  number. */
    27452746#define VERR_ISOMK_IMPORT_DIR_REC_VOLUME_SEQ_NO         (-25125)
    2746 /** Import ISO directory with an extent that is out of bounds. */
     2747/** Import ISO contains a directory with an extent that is out of bounds. */
    27472748#define VERR_ISOMK_IMPORT_DIR_REC_EXTENT_OUT_OF_BOUNDS  (-25126)
    2748 /** Import ISO directory with a bad record length. */
     2749/** Import ISO contains a directory with a bad record length. */
    27492750#define VERR_ISOMK_IMPORT_BAD_DIR_REC_LENGTH            (-25127)
    2750 /** Import ISO directory with a bad name length. */
     2751/** Import ISO contains a '.' or '..' directory record with a bad name
     2752 *  length. */
    27512753#define VERR_ISOMK_IMPORT_DOT_DIR_REC_BAD_NAME_LENGTH   (-25128)
    2752 /** Import ISO directory with a bad name. */
     2754/** Import ISO contains a '.' or '..' directory record with a bad name. */
    27532755#define VERR_ISOMK_IMPORT_DOT_DIR_REC_BAD_NAME          (-25129)
     2756/** Import ISO contains a directory with a more than one extent, that's
     2757 * currently not supported. */
     2758#define VERR_ISOMK_IMPORT_DIR_WITH_MORE_EXTENTS         (-25130)
     2759/** Import ISO contains a multi-extent directory record that differs
     2760 *  significantly from first record. */
     2761#define VERR_ISOMK_IMPORT_MISMATCHING_MULTI_EXTENT_REC  (-25131)
     2762/** Import ISO contains a non-final multi-extent directory record with a
     2763 *  size that isn't block aligned. */
     2764#define VERR_ISOMK_IMPORT_MISALIGNED_MULTI_EXTENT       (-25132)
     2765/** Import ISO contains a non-contigiuous multi-extent data, this is
     2766 * currently not supported. */
     2767#define VERR_ISOMK_IMPORT_NON_CONTIGUOUS_MULTI_EXTENT   (-25133)
     2768
    27542769/** The boot catalog block in the import ISO is out of bounds. */
    2755 #define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_OUT_OF_BOUNDS                (-25130)
     2770#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_OUT_OF_BOUNDS                (-25140)
    27562771/** The boot catalog block in the import ISO has an incorrect validation
    27572772 *  header ID. */
    2758 #define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_HEADER_ID         (-25131)
     2773#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_HEADER_ID         (-25141)
    27592774/** The boot catalog validation entry in the import ISO has incorrect keys. */
    2760 #define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_KEYS              (-25132)
     2775#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_KEYS              (-25142)
    27612776/** The boot catalog validation entry in the import ISO has an incorrect checksum. */
    2762 #define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_CHECKSUM          (-25133)
     2777#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_CHECKSUM          (-25143)
    27632778/** A boot catalog entry in the import ISO has an unknown type. */
    2764 #define VERR_ISOMK_IMPORT_BOOT_CAT_UNKNOWN_HEADER_ID                (-25134)
     2779#define VERR_ISOMK_IMPORT_BOOT_CAT_UNKNOWN_HEADER_ID                (-25144)
    27652780/** A boot catalog entry in the import ISO has an invalid boot media type. */
    2766 #define VERR_ISOMK_IMPORT_BOOT_CAT_INVALID_BOOT_MEDIA_TYPE          (-25135)
     2781#define VERR_ISOMK_IMPORT_BOOT_CAT_INVALID_BOOT_MEDIA_TYPE          (-25145)
    27672782/** The default boot catalog entry in the import ISO has invalid flags set. */
    2768 #define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_FLAGS          (-25136)
     2783#define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_FLAGS          (-25146)
    27692784/** A boot catalog entry in the import ISO has reserved flag set. */
    2770 #define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_RESERVED_FLAG              (-25137)
     2785#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_RESERVED_FLAG              (-25147)
    27712786/** A boot catalog entry in the import ISO is using the unused field. */
    2772 #define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_USES_UNUSED_FIELD          (-25138)
     2787#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_USES_UNUSED_FIELD          (-25148)
    27732788/** A boot catalog entry in the import ISO points to a block after the end of
    27742789 * the image input file. */
    2775 #define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_IMAGE_OUT_OF_BOUNDS        (-25139)
     2790#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_IMAGE_OUT_OF_BOUNDS        (-25149)
    27762791/** A boot catalog entry in the import ISO has an image with an
    27772792 * indeterminate size. */
    2778 #define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_UNKNOWN_IMAGE_SIZE         (-25140)
     2793#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_UNKNOWN_IMAGE_SIZE         (-25150)
    27792794/** The boot catalog in the import ISO is larger than a sector or it is
    27802795 *  missing the final section header entry. */
    2781 #define VERR_ISOMK_IMPORT_BOOT_CAT_MISSING_FINAL_OR_TOO_BIG         (-25141)
     2796#define VERR_ISOMK_IMPORT_BOOT_CAT_MISSING_FINAL_OR_TOO_BIG         (-25151)
    27822797/** The default boot catalog entry in the import ISO an invalid boot
    27832798 *  indicator value. */
    2784 #define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_BOOT_IND       (-25142)
     2799#define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_BOOT_IND       (-25152)
    27852800/** A boot catalog extension entry in the import ISO was either flagged
    27862801 *  incorrectly in the previous entry or has an invalid header ID. */
    2787 #define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_INVALID_ID             (-25143)
     2802#define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_INVALID_ID             (-25153)
    27882803/** A boot catalog extension entry in the import ISO uses undefined flags
    27892804 *  which will be lost. */
    2790 #define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_UNDEFINED_FLAGS        (-25144)
     2805#define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_UNDEFINED_FLAGS        (-25154)
    27912806/** A boot catalog extension entry in the import ISO indicates more entries when
    27922807 *  we reached the end of the boot catalog sector. */
    2793 #define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_END_OF_SECTOR          (-25145)
     2808#define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_END_OF_SECTOR          (-25155)
    27942809/** A boot catalog entry in the import ISO sets the continuation flag when using
    27952810 * NONE as the selection criteria type. */
    2796 #define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_WITH_NONE     (-25146)
     2811#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_WITH_NONE     (-25156)
    27972812/** A boot catalog entry in the import ISO sets the continuation flag when
    27982813 *  we reached the ned of the boot catalog secotr. */
    2799 #define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_EOS           (-25147)
     2814#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_EOS           (-25157)
     2815
    28002816/** @} */
    28012817
  • trunk/src/VBox/Runtime/common/fs/isomakerimport.cpp

    r67549 r67571  
    239239 *
    240240 * @returns IPRT status code (safe to ignore).
    241  * @param   pThis               The importer instance.
    242  * @param   pDirRec             The directory record.
    243  * @param   fNamespace          The namespace flag.
    244  * @param   idxParent           Parent directory.
    245  * @param   pszName             The name.
    246  * @param   cDepth              The depth to add it with.
    247  * @param   pTodoList           The todo list (for directories).
    248  */
    249 static int rtFsIsoImportProcessIso9660AddAndNameDirectory(PRTFSISOMKIMPORTER pThis, PCISO9660DIRREC pDirRec,
     241 * @param   pThis       The importer instance.
     242 * @param   pDirRec     The directory record.
     243 * @param   cbData      The actual directory data size.  (Always same as in the
     244 *                      directory record, but this what we do for files below.)
     245 * @param   fNamespace  The namespace flag.
     246 * @param   idxParent   Parent directory.
     247 * @param   pszName     The name.
     248 * @param   cDepth      The depth to add it with.
     249 * @param   pTodoList   The todo list (for directories).
     250 */
     251static int rtFsIsoImportProcessIso9660AddAndNameDirectory(PRTFSISOMKIMPORTER pThis, PCISO9660DIRREC pDirRec, uint64_t cbData,
    250252                                                          uint32_t fNamespace, uint32_t idxParent, const char *pszName,
    251253                                                          uint8_t cDepth, PRTLISTANCHOR pTodoList)
     
    273275            if (pImpDir)
    274276            {
    275                 pImpDir->cbDir       = ISO9660_GET_ENDIAN(&pDirRec->cbData);
     277                Assert((uint32_t)cbData == cbData /* no multi-extents for dirs makes it this far */);
     278                pImpDir->cbDir       = (uint32_t)cbData;
    276279                pImpDir->offDirBlock = ISO9660_GET_ENDIAN(&pDirRec->offExtent);
    277280                pImpDir->idxObj      = idxObj;
     
    295298 *
    296299 * @returns IPRT status code (safe to ignore).
    297  * @param   pThis               The importer instance.
    298  * @param   pDirRec             The directory record.
    299  * @param   fNamespace          The namespace flag.
    300  * @param   idxParent           Parent directory.
    301  * @param   pszName             The name.
    302  */
    303 static int rtFsIsoImportProcessIso9660AddAndNameFile(PRTFSISOMKIMPORTER pThis, PCISO9660DIRREC pDirRec,
     300 * @param   pThis       The importer instance.
     301 * @param   pDirRec     The directory record.
     302 * @param   cbData      The actual file data size.
     303 * @param   fNamespace  The namespace flag.
     304 * @param   idxParent   Parent directory.
     305 * @param   pszName     The name.
     306 */
     307static int rtFsIsoImportProcessIso9660AddAndNameFile(PRTFSISOMKIMPORTER pThis, PCISO9660DIRREC pDirRec, uint64_t cbData,
    304308                                                     uint32_t fNamespace, uint32_t idxParent, const char *pszName)
    305309{
     
    329333    PRTFSISOMKIMPBLOCK2FILE pBlock2File     = NULL;
    330334    PRTFSISOMKIMPBLOCK2FILE pBlock2FilePrev = NULL;
    331     if (ISO9660_GET_ENDIAN(&pDirRec->cbData) > 0) /* no data tracking for zero byte files */
     335    if (cbData > 0) /* no data tracking for zero byte files */
    332336    {
    333337        pBlock2File = (PRTFSISOMKIMPBLOCK2FILE)RTAvlU32Get(&pThis->Block2FileRoot, ISO9660_GET_ENDIAN(&pDirRec->offExtent));
     
    362366        rc = RTFsIsoMakerAddUnnamedFileWithCommonSrc(pThis->hIsoMaker, pThis->idxSrcFile,
    363367                                                     ISO9660_GET_ENDIAN(&pDirRec->offExtent) * (uint64_t)ISO9660_SECTOR_SIZE,
    364                                                      ISO9660_GET_ENDIAN(&pDirRec->cbData), NULL /*pObjInfo*/, &idxObj);
     368                                                     cbData, NULL /*pObjInfo*/, &idxObj);
    365369        if (RT_FAILURE(rc))
    366370            return rtFsIsoImpError(pThis, rc, "Error adding file '%s': %Rrc", pszName, rc);
     
    369373        /* Update statistics. */
    370374        pThis->pResults->cAddedFiles++;
    371         if (ISO9660_GET_ENDIAN(&pDirRec->cbData) > 0)
    372         {
    373             pThis->pResults->cbAddedDataBlocks += RT_ALIGN_32(ISO9660_GET_ENDIAN(&pDirRec->cbData), ISO9660_SECTOR_SIZE);
     375        if (cbData > 0)
     376        {
     377            pThis->pResults->cbAddedDataBlocks += RT_ALIGN_64(cbData, ISO9660_SECTOR_SIZE);
    374378
    375379            /* Lookup record. */
     
    450454    if (pDirRec->cbDirRec < RT_OFFSETOF(ISO9660DIRREC, achFileId) + pDirRec->bFileIdLength)
    451455        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_BAD_DIR_REC_LENGTH,
    452                                "Root dir record size is too small: %#x (min %#x)",
     456                               "Dir record size is too small: %#x (min %#x)",
    453457                               pDirRec->cbDirRec, RT_OFFSETOF(ISO9660DIRREC, achFileId) + pDirRec->bFileIdLength);
    454458    if (pDirRec->cbDirRec > cbMax)
    455459        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_BAD_DIR_REC_LENGTH,
    456                                "Root dir record size is too big: %#x (max %#x)", pDirRec->cbDirRec, cbMax);
     460                               "Dir record size is too big: %#x (max %#x)", pDirRec->cbDirRec, cbMax);
     461
     462    if (   (pDirRec->fFileFlags & (ISO9660_FILE_FLAGS_MULTI_EXTENT | ISO9660_FILE_FLAGS_DIRECTORY))
     463        ==                        (ISO9660_FILE_FLAGS_MULTI_EXTENT | ISO9660_FILE_FLAGS_DIRECTORY))
     464        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_DIR_WITH_MORE_EXTENTS,
     465                               "Multi-extent directories are not supported (cbData=%#RX32 offExtent=%#RX32)",
     466                               ISO9660_GET_ENDIAN(&pDirRec->cbData), ISO9660_GET_ENDIAN(&pDirRec->offExtent));
     467
    457468    return VINF_SUCCESS;
    458469}
     
    464475 * @returns IPRT status code (safe to ignore, see pThis->rc).
    465476 * @param   pThis               The importer instance.
    466  * @param   pDirRec             The root directory record to validate.
     477 * @param   pDirRec             The dot directory record to validate.
    467478 * @param   cbMax               The maximum size.
    468479 * @param   bName               The name byte (0x00: '.', 0x01: '..').
     
    484495
    485496
     497/**
     498 * rtFsIsoImportProcessIso9660TreeWorker helper that reads more data.
     499 *
     500 * @returns IPRT status code.
     501 * @param   pThis       The importer instance.
     502 * @param   ppDirRec    Pointer to the directory record pointer (in/out).
     503 * @param   pcbChunk    Pointer to the cbChunk variable (in/out).
     504 * @param   pcbDir      Pointer to the cbDir variable (in/out).  This indicates
     505 *                      how much we've left to read from the directory.
     506 * @param   poffNext    Pointer to the offNext variable (in/out).  This
     507 *                      indicates where the next chunk of directory data is in
     508 *                      the input file.
     509 */
     510static int rtFsIsoImportProcessIso9660TreeWorkerReadMore(PRTFSISOMKIMPORTER pThis, PCISO9660DIRREC *ppDirRec,
     511                                                         uint32_t *pcbChunk, uint32_t *pcbDir, uint64_t *poffNext)
     512{
     513    uint32_t cbChunk = *pcbChunk;
     514    *ppDirRec = (PCISO9660DIRREC)memmove(&pThis->abBuf[ISO9660_SECTOR_SIZE - cbChunk], *ppDirRec, cbChunk);
     515
     516    Assert(!(*poffNext & (ISO9660_SECTOR_SIZE - 1)));
     517    uint32_t cbToRead = RT_MIN(*pcbDir, sizeof(pThis->abBuf) - ISO9660_SECTOR_SIZE);
     518    int rc = RTVfsFileReadAt(pThis->hSrcFile, *poffNext, &pThis->abBuf[ISO9660_SECTOR_SIZE], cbToRead, NULL);
     519    if (RT_SUCCESS(rc))
     520    {
     521        Log3(("rtFsIsoImportProcessIso9660TreeWorker: Read %#zx more bytes @%#RX64, now got @%#RX64 LB %#RX32\n",
     522              cbToRead, *poffNext, *poffNext - cbChunk, cbChunk + cbToRead));
     523        *poffNext += cbToRead;
     524        *pcbDir   -= cbToRead;
     525        *pcbChunk  = cbChunk + cbToRead;
     526        return VINF_SUCCESS;
     527    }
     528    return rtFsIsoImpError(pThis, rc, "Error reading %#RX32 bytes at %#RX64 (dir): %Rrc", *poffNext, cbToRead);
     529}
     530
     531
     532/**
     533 * rtFsIsoImportProcessIso9660TreeWorker helper that deals with skipping to the
     534 * next sector when cbDirRec is zero.
     535 *
     536 * @returns IPRT status code.
     537 * @retval  VERR_NO_MORE_FILES when we reaches the end of the directory.
     538 * @param   pThis       The importer instance.
     539 * @param   ppDirRec    Pointer to the directory record pointer (in/out).
     540 * @param   pcbChunk    Pointer to the cbChunk variable (in/out).  Indicates how
     541 *                      much we've left to process starting and pDirRec.
     542 * @param   pcbDir      Pointer to the cbDir variable (in/out).  This indicates
     543 *                      how much we've left to read from the directory.
     544 * @param   poffNext    Pointer to the offNext variable (in/out).  This
     545 *                      indicates where the next chunk of directory data is in
     546 *                      the input file.
     547 */
     548static int rtFsIsoImportProcessIso9660TreeWorkerHandleZeroSizedDirRec(PRTFSISOMKIMPORTER pThis, PCISO9660DIRREC *ppDirRec,
     549                                                                      uint32_t *pcbChunk, uint32_t *pcbDir, uint64_t *poffNext)
     550{
     551    uint32_t cbChunk  = *pcbChunk;
     552    uint64_t offChunk = *poffNext - cbChunk;
     553    uint32_t cbSkip   = ISO9660_SECTOR_SIZE - ((uint32_t)offChunk & (ISO9660_SECTOR_SIZE - 1));
     554    if (cbSkip < cbChunk)
     555    {
     556        *ppDirRec = (PCISO9660DIRREC)((uintptr_t)*ppDirRec + cbSkip);
     557        *pcbChunk = cbChunk -= cbSkip;
     558        if (   cbChunk > UINT8_MAX
     559            || *pcbDir == 0)
     560        {
     561            Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> jumped %#RX32 to @%#RX64 LB %#RX32\n",
     562                  cbSkip, *poffNext - cbChunk, cbChunk));
     563            return VINF_SUCCESS;
     564        }
     565        Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> jumped %#RX32 to @%#RX64 LB %#RX32, but needs to read more\n",
     566              cbSkip, *poffNext - cbChunk, cbChunk));
     567        return rtFsIsoImportProcessIso9660TreeWorkerReadMore(pThis, ppDirRec, pcbChunk, pcbDir, poffNext);
     568    }
     569
     570    /* ASSUMES we're working in multiples of sectors! */
     571    if (*pcbDir == 0)
     572    {
     573        *pcbChunk = 0;
     574        return VERR_NO_MORE_FILES;
     575    }
     576
     577    /* End of chunk, read the next sectors. */
     578    Assert(!(*poffNext & (ISO9660_SECTOR_SIZE - 1)));
     579    uint32_t cbToRead = RT_MIN(*pcbDir, sizeof(pThis->abBuf));
     580    int rc = RTVfsFileReadAt(pThis->hSrcFile, *poffNext, pThis->abBuf, cbToRead, NULL);
     581    if (RT_SUCCESS(rc))
     582    {
     583        Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> Read %#zx more bytes @%#RX64, now got @%#RX64 LB %#RX32\n",
     584              cbToRead, *poffNext, *poffNext - cbChunk, cbChunk + cbToRead));
     585        *poffNext += cbToRead;
     586        *pcbDir   -= cbToRead;
     587        *pcbChunk  = cbChunk + cbToRead;
     588        *ppDirRec  = (PCISO9660DIRREC)&pThis->abBuf[0];
     589        return VINF_SUCCESS;
     590    }
     591    return rtFsIsoImpError(pThis, rc, "Error reading %#RX32 bytes at %#RX64 (dir): %Rrc", *poffNext, cbToRead);
     592}
     593
     594
     595/**
     596 * Deals with a single directory.
     597 *
     598 * @returns IPRT status code (safe to ignore, see pThis->rc).
     599 * @param   pThis               The importer instance.
     600 * @param   idxDir              The configuration index for the directory.
     601 * @param   offDirBlock         The offset of the directory data.
     602 * @param   cbDir               The size of the directory data.
     603 * @param   cDepth              The depth of the directory.
     604 * @param   fUnicode            Set if it's a unicode (UTF-16BE) encoded
     605 *                              directory.
     606 * @param   pTodoList           The todo-list to add sub-directories to.
     607 */
    486608static int rtFsIsoImportProcessIso9660TreeWorker(PRTFSISOMKIMPORTER pThis, uint32_t idxDir,
    487609                                                 uint32_t offDirBlock, uint32_t cbDir, uint8_t cDepth, bool fUnicode,
     
    498620     */
    499621    uint32_t cbChunk = RT_MIN(cbDir, sizeof(pThis->abBuf));
    500     uint64_t off    = (uint64_t)offDirBlock * ISO9660_SECTOR_SIZE;
    501     int rc = RTVfsFileReadAt(pThis->hSrcFile, off, pThis->abBuf, cbChunk, NULL);
     622    uint64_t offNext = (uint64_t)offDirBlock * ISO9660_SECTOR_SIZE;
     623    int rc = RTVfsFileReadAt(pThis->hSrcFile, offNext, pThis->abBuf, cbChunk, NULL);
    502624    if (RT_FAILURE(rc))
    503         return rtFsIsoImpError(pThis, rc, "Error reading directory at %#RX64 (%#RX32 / %#RX32): %Rrc", off, cbChunk, cbDir);
    504 
    505     cbDir -= cbChunk;
    506     off  += cbChunk;
     625        return rtFsIsoImpError(pThis, rc, "Error reading directory at %#RX64 (%#RX32 / %#RX32): %Rrc", offNext, cbChunk, cbDir);
     626
     627    cbDir   -= cbChunk;
     628    offNext += cbChunk;
    507629
    508630    /*
     
    527649     */
    528650    Log3(("rtFsIsoImportProcessIso9660TreeWorker: Starting at @%#RX64 LB %#RX32 (out of %#RX32) in %#x\n",
    529           off - cbChunk, cbChunk, cbChunk + cbDir, idxDir));
     651          offNext - cbChunk, cbChunk, cbChunk + cbDir, idxDir));
    530652    const uint32_t fNamespace = fUnicode ? RTFSISOMAKER_NAMESPACE_JOLIET : RTFSISOMAKER_NAMESPACE_ISO_9660;
    531     while (cbChunk > 0)
     653    while (   cbChunk > 0
     654           || cbDir   > 0)
    532655    {
    533656        /*
     
    539662        else
    540663        {
    541             pDirRec = (PCISO9660DIRREC)memmove(&pThis->abBuf[ISO9660_SECTOR_SIZE - cbChunk], pDirRec, cbChunk);
    542 
    543             Assert(!(off & (ISO9660_SECTOR_SIZE - 1)));
    544             uint32_t cbToRead = RT_MIN(cbDir, sizeof(pThis->abBuf) - ISO9660_SECTOR_SIZE);
    545             rc = RTVfsFileReadAt(pThis->hSrcFile, off, &pThis->abBuf[ISO9660_SECTOR_SIZE], cbToRead, NULL);
     664            rc = rtFsIsoImportProcessIso9660TreeWorkerReadMore(pThis, &pDirRec, &cbChunk, &cbDir, &offNext);
    546665            if (RT_FAILURE(rc))
    547                 return rtFsIsoImpError(pThis, rc, "Error reading %#RX32 bytes at %#RX64 (dir): %Rrc", off, cbToRead);
    548 
    549             Log3(("rtFsIsoImportProcessIso9660TreeWorker: Read %#zx more bytes @%#RX64, now got @%#RX64 LB %#RX32\n",
    550                   cbToRead, off, off - cbChunk, cbChunk + cbToRead));
    551             off     += cbToRead;
    552             cbDir   -= cbToRead;
    553             cbChunk += cbToRead;
     666                return rc;
    554667        }
    555668
    556669        /* If null length, skip to the next sector.  May have to read some then. */
    557         if (pDirRec->cbDirRec == 0)
    558         {
    559             uint64_t offChunk = off - cbChunk;
    560             uint32_t cbSkip   = ISO9660_SECTOR_SIZE - ((uint32_t)offChunk & (ISO9660_SECTOR_SIZE - 1));
    561             if (cbSkip < cbChunk)
     670        if (pDirRec->cbDirRec != 0)
     671        { /* likely */ }
     672        else
     673        {
     674            rc = rtFsIsoImportProcessIso9660TreeWorkerHandleZeroSizedDirRec(pThis, &pDirRec, &cbChunk, &cbDir, &offNext);
     675            if (RT_FAILURE(rc))
    562676            {
    563                 pDirRec  = (PCISO9660DIRREC)((uintptr_t)pDirRec + cbSkip);
    564                 cbChunk -= cbSkip;
    565                 if (   cbChunk <= UINT8_MAX
    566                     && cbDir == 0)
    567                 {
    568                     Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> Restart loop\n"));
    569                     continue;
    570                 }
    571                 Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> jumped %#RX32 to @%#RX64 LB %#RX32\n",
    572                       cbSkip, off - cbChunk, cbChunk));
     677                if (rc == VERR_NO_MORE_FILES)
     678                    break;
     679                return rc;
    573680            }
    574             /* ASSUMES we're working in multiples of sectors! */
    575             else if (cbDir == 0)
    576                 break;
    577             else
    578             {
    579                 Assert(!(off & (ISO9660_SECTOR_SIZE - 1)));
    580                 uint32_t cbToRead = RT_MIN(cbDir, sizeof(pThis->abBuf));
    581                 rc = RTVfsFileReadAt(pThis->hSrcFile, off, pThis->abBuf, cbToRead, NULL);
    582                 if (RT_FAILURE(rc))
    583                     return rtFsIsoImpError(pThis, rc, "Error reading %#RX32 bytes at %#RX64 (dir): %Rrc", off, cbToRead);
    584 
    585                 Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> Read %#zx more bytes @%#RX64, now got @%#RX64 LB %#RX32\n",
    586                       cbToRead, off, off - cbChunk, cbChunk + cbToRead));
    587                 off     += cbToRead;
    588                 cbDir   -= cbToRead;
    589                 cbChunk += cbToRead;
    590                 pDirRec = (PCISO9660DIRREC)&pThis->abBuf[0];
    591             }
     681            if (pDirRec->cbDirRec == 0)
     682                continue;
    592683        }
    593684
     
    600691        uint8_t const * const pbSys = (uint8_t const *)&pDirRec->achFileId[pDirRec->bFileIdLength + !(pDirRec->bFileIdLength & 1)];
    601692        Log3(("pDirRec=&abBuf[%#07zx]: @%#010RX64 cb=%#04x ff=%#04x off=%#010RX32 cb=%#010RX32 cbSys=%#x id=%.*Rhxs\n",
    602               (uintptr_t)pDirRec - (uintptr_t)&pThis->abBuf[0], off - cbChunk, pDirRec->cbDirRec, pDirRec->fFileFlags,
     693              (uintptr_t)pDirRec - (uintptr_t)&pThis->abBuf[0], offNext - cbChunk, pDirRec->cbDirRec, pDirRec->fFileFlags,
    603694              ISO9660_GET_ENDIAN(&pDirRec->offExtent), ISO9660_GET_ENDIAN(&pDirRec->cbData), cbSys,
    604695              pDirRec->bFileIdLength, pDirRec->achFileId));
     
    606697        if (RT_FAILURE(rc))
    607698            return rc;
     699
     700        /* This early calculation of the next record is due to multi-extent
     701           handling further down. */
     702        uint32_t        cbChunkNew  = cbChunk - pDirRec->cbDirRec;
     703        PCISO9660DIRREC pDirRecNext = (PCISO9660DIRREC)((uintptr_t)pDirRec + pDirRec->cbDirRec);
    608704
    609705        /*
     
    649745
    650746            /*
    651              * Add the object.
     747             * Deal with multi-extent files (usually large ones).  We currently only
     748             * handle files where the data is in single continuous chunk and only split
     749             * up into multiple directory records because of data type limitations.
    652750             */
    653             if (pDirRec->fFileFlags & ISO9660_FILE_FLAGS_DIRECTORY)
    654                 rtFsIsoImportProcessIso9660AddAndNameDirectory(pThis, pDirRec, fNamespace, idxDir,
    655                                                                pThis->szNameBuf, cDepth + 1, pTodoList);
     751            uint8_t  abDirRecCopy[256];
     752            uint64_t cbData = ISO9660_GET_ENDIAN(&pDirRec->cbData);
     753            if (!(pDirRec->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT))
     754            { /* likely */ }
    656755            else
    657                 rtFsIsoImportProcessIso9660AddAndNameFile(pThis, pDirRec, fNamespace, idxDir, pThis->szNameBuf);
     756            {
     757                if (cbData & (ISO9660_SECTOR_SIZE - 1))
     758                    return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_MISALIGNED_MULTI_EXTENT,
     759                                           "The size of non-final multi-extent record #0x0 isn't block aligned: %#RX64", cbData);
     760
     761                /* Make a copy of the first directory record so we don't overwrite
     762                   it when reading in more records below.  */
     763                pDirRec = (PCISO9660DIRREC)memcpy(abDirRecCopy, pDirRec, pDirRec->cbDirRec);
     764
     765                /* Process extent records. */
     766                uint32_t cDirRecs     = 1;
     767                uint32_t offNextBlock = ISO9660_GET_ENDIAN(&pDirRec->offExtent)
     768                                      + ISO9660_GET_ENDIAN(&pDirRec->cbData) / ISO9660_SECTOR_SIZE;
     769                while (   cbChunkNew > 0
     770                       || cbDir > 0)
     771                {
     772                    /* Read more? Skip? */
     773                    if (   cbChunkNew <= UINT8_MAX
     774                        && cbDir != 0)
     775                    {
     776                        rc = rtFsIsoImportProcessIso9660TreeWorkerReadMore(pThis, &pDirRecNext, &cbChunkNew, &cbDir, &offNext);
     777                        if (RT_FAILURE(rc))
     778                            return rc;
     779                    }
     780                    if (pDirRecNext->cbDirRec == 0)
     781                    {
     782                        rc = rtFsIsoImportProcessIso9660TreeWorkerHandleZeroSizedDirRec(pThis, &pDirRecNext, &cbChunkNew,
     783                                                                                        &cbDir, &offNext);
     784                        if (RT_FAILURE(rc))
     785                        {
     786                            if (rc == VERR_NO_MORE_FILES)
     787                                break;
     788                            return rc;
     789                        }
     790                        if (pDirRecNext->cbDirRec == 0)
     791                            continue;
     792                    }
     793
     794                    /* Check the next record. */
     795                    rc = rtFsIsoImportValidateDirRec(pThis, pDirRecNext, cbChunkNew);
     796                    if (RT_FAILURE(rc))
     797                        return rc;
     798                    if (pDirRecNext->bFileIdLength != pDirRec->bFileIdLength)
     799                        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_MISMATCHING_MULTI_EXTENT_REC,
     800                                               "Multi-extent record #%#x differs from the first: bFileIdLength is %#x, expected %#x",
     801                                               cDirRecs, pDirRecNext->bFileIdLength, pDirRec->bFileIdLength);
     802                    if (memcmp(pDirRecNext->achFileId, pDirRec->achFileId, pDirRec->bFileIdLength) != 0)
     803                        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_MISMATCHING_MULTI_EXTENT_REC,
     804                                               "Multi-extent record #%#x differs from the first: achFileId is %.*Rhxs, expected %.*Rhxs",
     805                                               cDirRecs, pDirRecNext->bFileIdLength, pDirRecNext->achFileId,
     806                                               pDirRec->bFileIdLength, pDirRec->achFileId);
     807                    if (ISO9660_GET_ENDIAN(&pDirRecNext->VolumeSeqNo) != ISO9660_GET_ENDIAN(&pDirRec->VolumeSeqNo))
     808                        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_MISMATCHING_MULTI_EXTENT_REC,
     809                                               "Multi-extent record #%#x differs from the first: VolumeSeqNo is %#x, expected %#x",
     810                                               cDirRecs, ISO9660_GET_ENDIAN(&pDirRecNext->VolumeSeqNo),
     811                                               ISO9660_GET_ENDIAN(&pDirRec->VolumeSeqNo));
     812                    if (   (pDirRecNext->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT)
     813                        && (ISO9660_GET_ENDIAN(&pDirRecNext->cbData) & (ISO9660_SECTOR_SIZE - 1)) )
     814                        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_MISALIGNED_MULTI_EXTENT,
     815                                               "The size of non-final multi-extent record #%#x isn't block aligned: %#RX32",
     816                                               cDirRecs, ISO9660_GET_ENDIAN(&pDirRecNext->cbData));
     817
     818                    /* Check that the data is contiguous, then add the data.  */
     819                    if (ISO9660_GET_ENDIAN(&pDirRecNext->offExtent) == offNextBlock)
     820                        cbData += ISO9660_GET_ENDIAN(&pDirRecNext->cbData);
     821                    else
     822                        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_NON_CONTIGUOUS_MULTI_EXTENT,
     823                                               "Multi-extent record #%#x isn't contiguous: offExtent=%#RX32, expected %#RX32",
     824                                               cDirRecs, ISO9660_GET_ENDIAN(&pDirRecNext->offExtent), offNextBlock);
     825
     826                    /* Advance. */
     827                    cDirRecs++;
     828                    bool fDone  = !(pDirRecNext->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT);
     829                    offNext    += ISO9660_GET_ENDIAN(&pDirRecNext->cbData) / ISO9660_SECTOR_SIZE;
     830                    cbChunkNew -= pDirRecNext->cbDirRec;
     831                    pDirRecNext = (PCISO9660DIRREC)((uintptr_t)pDirRecNext + pDirRecNext->cbDirRec);
     832                    if (fDone)
     833                        break;
     834                }
     835            }
     836            if (RT_SUCCESS(rc))
     837            {
     838                /*
     839                 * Add the object.
     840                 */
     841                if (pDirRec->fFileFlags & ISO9660_FILE_FLAGS_DIRECTORY)
     842                    rtFsIsoImportProcessIso9660AddAndNameDirectory(pThis, pDirRec, cbData, fNamespace, idxDir,
     843                                                                   pThis->szNameBuf, cDepth + 1, pTodoList);
     844                else
     845                    rtFsIsoImportProcessIso9660AddAndNameFile(pThis, pDirRec, cbData, fNamespace, idxDir, pThis->szNameBuf);
     846            }
    658847        }
    659848        else
    660849            rtFsIsoImpError(pThis, rc, "Invalid name at %#RX64: %.Rhxs",
    661                             off - cbChunk, pDirRec->bFileIdLength, pDirRec->achFileId);
     850                            offNext - cbChunk, pDirRec->bFileIdLength, pDirRec->achFileId);
    662851
    663852        /*
    664853         * Advance to the next directory record.
    665854         */
    666         cbChunk -= pDirRec->cbDirRec;
    667         pDirRec = (PCISO9660DIRREC)((uintptr_t)pDirRec + pDirRec->cbDirRec);
     855        cbChunk = cbChunkNew;
     856        pDirRec = pDirRecNext;
    668857    }
    669858
     
    672861
    673862
     863/**
     864 * Deals with a directory tree.
     865 *
     866 * This is implemented by tracking directories that needs to be processed in a
     867 * todo list, so no recursive calls, however it uses a bit of heap.
     868 *
     869 * @returns IPRT status code (safe to ignore, see pThis->rc).
     870 * @param   pThis               The importer instance.
     871 * @param   offDirBlock         The offset of the root directory data.
     872 * @param   cbDir               The size of the root directory data.
     873 * @param   fUnicode            Set if it's a unicode (UTF-16BE) encoded
     874 *                              directory.
     875 */
    674876static int rtFsIsoImportProcessIso9660Tree(PRTFSISOMKIMPORTER pThis, uint32_t offDirBlock, uint32_t cbDir, bool fUnicode)
    675877{
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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