@@ -862,6 +862,193 @@ int FIO_compressFilename(const char* dstFileName, const char* srcFileName,
862
862
return result ;
863
863
}
864
864
865
+ typedef struct {
866
+ int numActualFrames ;
867
+ int numSkippableFrames ;
868
+ unsigned long long decompressedSize ;
869
+ int canComputeDecompSize ;
870
+ unsigned long long compressedSize ;
871
+ int usesCheck ;
872
+ } fileInfo_t ;
873
+
874
+
875
+ int calcFrameHeaderSize (BYTE frameHeaderDescriptor ){
876
+ int frameContentSizeBytes = 0 ;
877
+ int windowDescriptorBytes ;
878
+ int dictionaryIDBytes ;
879
+ int frameContentSizeFlag = frameHeaderDescriptor >> 6 ;
880
+ int singleSegmentFlag = (frameHeaderDescriptor & (1 << 5 )) >> 5 ;
881
+ int dictionaryIDFlag = frameHeaderDescriptor & 3 ;
882
+ if (frameContentSizeFlag != 0 ){
883
+ frameContentSizeBytes = 1 << frameContentSizeFlag ;
884
+ }
885
+ else if (singleSegmentFlag ){
886
+ frameContentSizeBytes = 1 ;
887
+ }
888
+ windowDescriptorBytes = singleSegmentFlag ? 0 : 1 ;
889
+ dictionaryIDBytes = dictionaryIDFlag ? 1 << (dictionaryIDFlag - 1 ): 0 ;
890
+ return 4 + 1 + windowDescriptorBytes + frameContentSizeBytes + dictionaryIDBytes ;
891
+ }
892
+
893
+ /*
894
+ * Reads information from file, stores in *info
895
+ * if successful, returns 0, otherwise returns 1
896
+ */
897
+ int getFileInfo (fileInfo_t * info , const char * inFileName ){
898
+ FILE * srcFile = FIO_openSrcFile (inFileName );
899
+ if (srcFile == NULL ){
900
+ return 1 ;
901
+ }
902
+ info -> compressedSize = (unsigned long long )UTIL_getFileSize (inFileName );
903
+ info -> decompressedSize = 0 ;
904
+ info -> numActualFrames = 0 ;
905
+ info -> numSkippableFrames = 0 ;
906
+ info -> canComputeDecompSize = 1 ;
907
+ /* begin analyzing frame */
908
+ while (1 ){
909
+ BYTE magicNumberBuffer [4 ];
910
+ size_t numBytesRead = fread (magicNumberBuffer , 1 , 4 , srcFile );
911
+ U32 magicNumber ;
912
+ if (numBytesRead != 4 ) break ;
913
+ magicNumber = MEM_readLE32 (magicNumberBuffer );
914
+ if (magicNumber == ZSTD_MAGICNUMBER ){
915
+ BYTE frameHeaderDescriptor ;
916
+ int totalFrameHeaderBytes ;
917
+ BYTE * frameHeader ;
918
+ int lastBlock = 0 ;
919
+ size_t readBytes = fread (& frameHeaderDescriptor , 1 , 1 , srcFile );
920
+ info -> numActualFrames ++ ;
921
+ if (readBytes != 1 ){
922
+ DISPLAY ("There was an error with reading frame header descriptor\n" );
923
+ exit (1 );
924
+ }
925
+ /* calculate actual frame header size */
926
+ totalFrameHeaderBytes = calcFrameHeaderSize (frameHeaderDescriptor );
927
+
928
+ /* reset to beginning of from and read entire header */
929
+ fseek (srcFile , -5 , SEEK_CUR );
930
+ frameHeader = (BYTE * )malloc (totalFrameHeaderBytes );
931
+ readBytes = fread (frameHeader , 1 , totalFrameHeaderBytes , srcFile );
932
+ if (readBytes != (size_t )totalFrameHeaderBytes ){
933
+ DISPLAY ("There was an error reading the frame header\n" );
934
+ exit (1 );
935
+ }
936
+
937
+ /* get decompressed file size */
938
+ {
939
+ U64 additional = ZSTD_getFrameContentSize (frameHeader , totalFrameHeaderBytes );
940
+ if (additional != ZSTD_CONTENTSIZE_UNKNOWN && additional != ZSTD_CONTENTSIZE_ERROR ){
941
+ info -> decompressedSize += additional ;
942
+ }
943
+ else {
944
+ info -> canComputeDecompSize = 0 ;
945
+ }
946
+ }
947
+
948
+ /* skip the rest of the blocks in the frame */
949
+ do {
950
+ BYTE blockHeaderBuffer [3 ];
951
+ U32 blockHeader ;
952
+ int blockSize ;
953
+ readBytes = fread (blockHeaderBuffer , 1 , 3 , srcFile );
954
+ if (readBytes != 3 ){
955
+ DISPLAY ("There was a problem reading the block header\n" );
956
+ exit (1 );
957
+ }
958
+ blockHeader = MEM_readLE24 (blockHeaderBuffer );
959
+ lastBlock = blockHeader & 1 ;
960
+ blockSize = (blockHeader - (blockHeader & 7 )) >> 3 ;
961
+ fseek (srcFile , blockSize , SEEK_CUR );
962
+ }while (lastBlock != 1 );
963
+ {
964
+ /* check if checksum is used */
965
+ int contentChecksumFlag = (frameHeaderDescriptor & (1 << 2 )) >> 2 ;
966
+ if (contentChecksumFlag ){
967
+ info -> usesCheck = 1 ;
968
+ }
969
+ if (contentChecksumFlag ){
970
+ fseek (srcFile , 4 , SEEK_CUR );
971
+ }
972
+ }
973
+ }
974
+ else if (magicNumber == ZSTD_MAGIC_SKIPPABLE_START ){
975
+ BYTE frameSizeBuffer [4 ];
976
+ long frameSize ;
977
+ size_t readBytes = fread (frameSizeBuffer , 1 , 4 , srcFile );
978
+ info -> numSkippableFrames ++ ;
979
+ if (readBytes != 4 ){
980
+ DISPLAY ("There was an error reading skippable frame size" );
981
+ exit (1 );
982
+ }
983
+ frameSize = MEM_readLE32 (frameSizeBuffer );
984
+ fseek (srcFile , frameSize , SEEK_CUR );
985
+ }
986
+
987
+ }
988
+ return 0 ;
989
+ }
990
+ void displayInfo (const char * inFileName , fileInfo_t * info , int displayLevel ){
991
+ double compressedSizeMB = (double )info -> compressedSize /(1 MB );
992
+ double decompressedSizeMB = (double )info -> decompressedSize /(1 MB );
993
+
994
+ if (displayLevel <=2 ){
995
+ if (info -> usesCheck && info -> canComputeDecompSize ){
996
+ DISPLAY ("Skippable Non-Skippable Compressed Uncompressed Ratio Check Filename\n" );
997
+ DISPLAY ("%9d %13d %7.2f MB %7.2f MB %5.3f XXH64 %s\n" ,
998
+ info -> numSkippableFrames , info -> numActualFrames , compressedSizeMB , decompressedSizeMB ,
999
+ compressedSizeMB /decompressedSizeMB , inFileName );
1000
+ }
1001
+ else if (!info -> usesCheck ){
1002
+ DISPLAY ("Skippable Non-Skippable Compressed Uncompressed Ratio Check Filename\n" );
1003
+ DISPLAY ("%9d %13d %7.2f MB %7.2f MB %5.3f %s\n" ,
1004
+ info -> numSkippableFrames , info -> numActualFrames , compressedSizeMB , decompressedSizeMB ,
1005
+ compressedSizeMB /decompressedSizeMB , inFileName );
1006
+ }
1007
+ else if (!info -> canComputeDecompSize ){
1008
+ DISPLAY ("Skippable Non-Skippable Compressed Uncompressed Ratio Check Filename\n" );
1009
+ DISPLAY ("%9d %13d %7.2f MB XXH64 %s\n" ,
1010
+ info -> numSkippableFrames , info -> numActualFrames , compressedSizeMB , inFileName );
1011
+ }
1012
+ else {
1013
+ DISPLAY ("Skippable Non-Skippable Filename\n" );
1014
+ DISPLAY ("%9d %13d %7.2f MB %s\n" ,
1015
+ info -> numSkippableFrames , info -> numActualFrames , compressedSizeMB , inFileName );
1016
+ }
1017
+ }
1018
+ else {
1019
+ DISPLAY ("# Zstandard Frames: %d\n" , info -> numActualFrames );
1020
+ DISPLAY ("# Skippable Frames: %d\n" , info -> numSkippableFrames );
1021
+ DISPLAY ("Compressed Size: %.2f MB (%llu B)\n" , compressedSizeMB , info -> compressedSize );
1022
+ if (info -> canComputeDecompSize ){
1023
+ DISPLAY ("Decompressed Size: %.2f MB (%llu B)\n" , decompressedSizeMB , info -> decompressedSize );
1024
+ DISPLAY ("Ratio: %.4f\n" , compressedSizeMB /decompressedSizeMB );
1025
+ }
1026
+ if (info -> usesCheck ){
1027
+ DISPLAY ("Check: XXH64\n" );
1028
+ }
1029
+ }
1030
+
1031
+ }
1032
+
1033
+ int FIO_listFile (const char * inFileName , int displayLevel ){
1034
+ const char * const suffixPtr = strrchr (inFileName , '.' );
1035
+ DISPLAY ("File: %s\n" , inFileName );
1036
+ if (!suffixPtr || strcmp (suffixPtr , ZSTD_EXTENSION )){
1037
+ DISPLAYLEVEL (1 , "file %s was not compressed with zstd -- ignoring\n\n" , inFileName );
1038
+ return 1 ;
1039
+ }
1040
+ else {
1041
+ fileInfo_t * info = (fileInfo_t * )malloc (sizeof (fileInfo_t ));
1042
+ int error = getFileInfo (info , inFileName );
1043
+ if (error == 1 ){
1044
+ DISPLAY ("An error occurred with getting file info\n" );
1045
+ exit (1 );
1046
+ }
1047
+ displayInfo (inFileName , info , displayLevel );
1048
+ }
1049
+ DISPLAY ("\n" );
1050
+ return 0 ;
1051
+ }
865
1052
866
1053
int FIO_compressMultipleFilenames (const char * * inFileNamesTable , unsigned nbFiles ,
867
1054
const char * suffix ,
0 commit comments