| 2811 | } |
| 2812 | |
| 2813 | static InfoError |
| 2814 | FIO_analyzeFrames(fileInfo_t* info, FILE* const srcFile) |
| 2815 | { |
| 2816 | /* begin analyzing frame */ |
| 2817 | for ( ; ; ) { |
| 2818 | BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; |
| 2819 | size_t const numBytesRead = fread(headerBuffer, 1, sizeof(headerBuffer), srcFile); |
| 2820 | if (numBytesRead < ZSTD_FRAMEHEADERSIZE_MIN(ZSTD_f_zstd1)) { |
| 2821 | if ( feof(srcFile) |
| 2822 | && (numBytesRead == 0) |
| 2823 | && (info->compressedSize > 0) |
| 2824 | && (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) { |
| 2825 | unsigned long long file_position = (unsigned long long) LONG_TELL(srcFile); |
| 2826 | unsigned long long file_size = (unsigned long long) info->compressedSize; |
| 2827 | ERROR_IF(file_position != file_size, info_truncated_input, |
| 2828 | "Error: seeked to position %llu, which is beyond file size of %llu\n", |
| 2829 | file_position, |
| 2830 | file_size); |
| 2831 | break; /* correct end of file => success */ |
| 2832 | } |
| 2833 | ERROR_IF(feof(srcFile), info_not_zstd, "Error: reached end of file with incomplete frame"); |
| 2834 | ERROR_IF(1, info_frame_error, "Error: did not reach end of file but ran out of frames"); |
| 2835 | } |
| 2836 | { U32 const magicNumber = MEM_readLE32(headerBuffer); |
| 2837 | /* Zstandard frame */ |
| 2838 | if (magicNumber == ZSTD_MAGICNUMBER) { |
| 2839 | ZSTD_frameHeader header; |
| 2840 | U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead); |
| 2841 | if ( frameContentSize == ZSTD_CONTENTSIZE_ERROR |
| 2842 | || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN ) { |
| 2843 | info->decompUnavailable = 1; |
| 2844 | } else { |
| 2845 | info->decompressedSize += frameContentSize; |
| 2846 | } |
| 2847 | ERROR_IF(ZSTD_getFrameHeader(&header, headerBuffer, numBytesRead) != 0, |
| 2848 | info_frame_error, "Error: could not decode frame header"); |
| 2849 | info->windowSize = header.windowSize; |
| 2850 | /* move to the end of the frame header */ |
| 2851 | { size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead); |
| 2852 | ERROR_IF(ZSTD_isError(headerSize), info_frame_error, "Error: could not determine frame header size"); |
| 2853 | ERROR_IF(fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR) != 0, |
| 2854 | info_frame_error, "Error: could not move to end of frame header"); |
| 2855 | } |
| 2856 | |
| 2857 | /* skip all blocks in the frame */ |
| 2858 | { int lastBlock = 0; |
| 2859 | do { |
| 2860 | BYTE blockHeaderBuffer[3]; |
| 2861 | ERROR_IF(fread(blockHeaderBuffer, 1, 3, srcFile) != 3, |
| 2862 | info_frame_error, "Error while reading block header"); |
| 2863 | { U32 const blockHeader = MEM_readLE24(blockHeaderBuffer); |
| 2864 | U32 const blockTypeID = (blockHeader >> 1) & 3; |
| 2865 | U32 const isRLE = (blockTypeID == 1); |
| 2866 | U32 const isWrongBlock = (blockTypeID == 3); |
| 2867 | long const blockSize = isRLE ? 1 : (long)(blockHeader >> 3); |
| 2868 | ERROR_IF(isWrongBlock, info_frame_error, "Error: unsupported block type"); |
| 2869 | lastBlock = blockHeader & 1; |
| 2870 | ERROR_IF(fseek(srcFile, blockSize, SEEK_CUR) != 0, |
no test coverage detected