mirror of
https://github.com/facebook/zstd.git
synced 2025-11-28 00:04:28 -05:00
minor refactoring of --list
trying to reduce recurrent patterns.
This commit is contained in:
parent
9bce916732
commit
9b45db7fa6
@ -1988,22 +1988,19 @@ typedef struct {
|
|||||||
U32 nbFiles;
|
U32 nbFiles;
|
||||||
} fileInfo_t;
|
} fileInfo_t;
|
||||||
|
|
||||||
/** getFileInfo() :
|
typedef enum { info_success=0, info_frame_error=1, info_not_zstd=2, info_file_error=3 } InfoError;
|
||||||
* Reads information from file, stores in *info
|
|
||||||
* @return : 0 if successful
|
|
||||||
* 1 for frame analysis error
|
|
||||||
* 2 for file not compressed with zstd
|
|
||||||
* 3 for cases in which file could not be opened.
|
|
||||||
*/
|
|
||||||
static int getFileInfo_fileConfirmed(fileInfo_t* info, const char* inFileName){
|
|
||||||
int detectError = 0;
|
|
||||||
FILE* const srcFile = FIO_openSrcFile(inFileName);
|
|
||||||
if (srcFile == NULL) {
|
|
||||||
DISPLAY("Error: could not open source file %s\n", inFileName);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
info->compressedSize = UTIL_getFileSize(inFileName);
|
|
||||||
|
|
||||||
|
#define EXIT_IF(c,n,...) { \
|
||||||
|
if (c) { \
|
||||||
|
DISPLAYLEVEL(1, __VA_ARGS__); \
|
||||||
|
DISPLAYLEVEL(1, " \n"); \
|
||||||
|
return n; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static InfoError
|
||||||
|
FIO_analyzeFrames(fileInfo_t* info, FILE* const srcFile)
|
||||||
|
{
|
||||||
/* begin analyzing frame */
|
/* begin analyzing frame */
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
|
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
|
||||||
@ -2013,130 +2010,111 @@ static int getFileInfo_fileConfirmed(fileInfo_t* info, const char* inFileName){
|
|||||||
&& (numBytesRead == 0)
|
&& (numBytesRead == 0)
|
||||||
&& (info->compressedSize > 0)
|
&& (info->compressedSize > 0)
|
||||||
&& (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) {
|
&& (info->compressedSize != UTIL_FILESIZE_UNKNOWN) ) {
|
||||||
break;
|
return 0; /* successful end of file */
|
||||||
}
|
|
||||||
else if (feof(srcFile)) {
|
|
||||||
DISPLAY("Error: reached end of file with incomplete frame\n");
|
|
||||||
detectError = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DISPLAY("Error: did not reach end of file but ran out of frames\n");
|
|
||||||
detectError = 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
EXIT_IF(feof(srcFile), info_not_zstd, "Error: reached end of file with incomplete frame");
|
||||||
|
EXIT_IF(1, info_frame_error, "Error: did not reach end of file but ran out of frames");
|
||||||
}
|
}
|
||||||
{ U32 const magicNumber = MEM_readLE32(headerBuffer);
|
{ U32 const magicNumber = MEM_readLE32(headerBuffer);
|
||||||
/* Zstandard frame */
|
/* Zstandard frame */
|
||||||
if (magicNumber == ZSTD_MAGICNUMBER) {
|
if (magicNumber == ZSTD_MAGICNUMBER) {
|
||||||
ZSTD_frameHeader header;
|
ZSTD_frameHeader header;
|
||||||
U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead);
|
U64 const frameContentSize = ZSTD_getFrameContentSize(headerBuffer, numBytesRead);
|
||||||
if (frameContentSize == ZSTD_CONTENTSIZE_ERROR || frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN) {
|
if ( frameContentSize == ZSTD_CONTENTSIZE_ERROR
|
||||||
|
|| frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN ) {
|
||||||
info->decompUnavailable = 1;
|
info->decompUnavailable = 1;
|
||||||
} else {
|
} else {
|
||||||
info->decompressedSize += frameContentSize;
|
info->decompressedSize += frameContentSize;
|
||||||
}
|
}
|
||||||
if (ZSTD_getFrameHeader(&header, headerBuffer, numBytesRead) != 0) {
|
EXIT_IF(ZSTD_getFrameHeader(&header, headerBuffer, numBytesRead) != 0,
|
||||||
DISPLAY("Error: could not decode frame header\n");
|
info_frame_error, "Error: could not decode frame header");
|
||||||
detectError = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
info->windowSize = header.windowSize;
|
info->windowSize = header.windowSize;
|
||||||
/* move to the end of the frame header */
|
/* move to the end of the frame header */
|
||||||
{ size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead);
|
{ size_t const headerSize = ZSTD_frameHeaderSize(headerBuffer, numBytesRead);
|
||||||
if (ZSTD_isError(headerSize)) {
|
EXIT_IF(ZSTD_isError(headerSize), 1, "Error: could not determine frame header size");
|
||||||
DISPLAY("Error: could not determine frame header size\n");
|
EXIT_IF(fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR) != 0,
|
||||||
detectError = 1;
|
info_frame_error, "Error: could not move to end of frame header");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
{ int const ret = fseek(srcFile, ((long)headerSize)-((long)numBytesRead), SEEK_CUR);
|
|
||||||
if (ret != 0) {
|
|
||||||
DISPLAY("Error: could not move to end of frame header\n");
|
|
||||||
detectError = 1;
|
|
||||||
break;
|
|
||||||
} } }
|
|
||||||
|
|
||||||
/* skip the rest of the blocks in the frame */
|
/* skip all blocks in the frame */
|
||||||
{ int lastBlock = 0;
|
{ int lastBlock = 0;
|
||||||
do {
|
do {
|
||||||
BYTE blockHeaderBuffer[3];
|
BYTE blockHeaderBuffer[3];
|
||||||
size_t const readBytes = fread(blockHeaderBuffer, 1, 3, srcFile);
|
EXIT_IF(fread(blockHeaderBuffer, 1, 3, srcFile) != 3,
|
||||||
if (readBytes != 3) {
|
info_frame_error, "Error while reading block header");
|
||||||
DISPLAY("There was a problem reading the block header\n");
|
|
||||||
detectError = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
{ U32 const blockHeader = MEM_readLE24(blockHeaderBuffer);
|
{ U32 const blockHeader = MEM_readLE24(blockHeaderBuffer);
|
||||||
U32 const blockTypeID = (blockHeader >> 1) & 3;
|
U32 const blockTypeID = (blockHeader >> 1) & 3;
|
||||||
U32 const isRLE = (blockTypeID == 1);
|
U32 const isRLE = (blockTypeID == 1);
|
||||||
U32 const isWrongBlock = (blockTypeID == 3);
|
U32 const isWrongBlock = (blockTypeID == 3);
|
||||||
long const blockSize = isRLE ? 1 : (long)(blockHeader >> 3);
|
long const blockSize = isRLE ? 1 : (long)(blockHeader >> 3);
|
||||||
if (isWrongBlock) {
|
EXIT_IF(isWrongBlock, info_frame_error, "Error: unsupported block type");
|
||||||
DISPLAY("Error: unsupported block type \n");
|
|
||||||
detectError = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastBlock = blockHeader & 1;
|
lastBlock = blockHeader & 1;
|
||||||
{ int const ret = fseek(srcFile, blockSize, SEEK_CUR);
|
EXIT_IF(fseek(srcFile, blockSize, SEEK_CUR) != 0,
|
||||||
if (ret != 0) {
|
info_frame_error, "Error: could not skip to end of block");
|
||||||
DISPLAY("Error: could not skip to end of block\n");
|
}
|
||||||
detectError = 1;
|
|
||||||
break;
|
|
||||||
} } }
|
|
||||||
} while (lastBlock != 1);
|
} while (lastBlock != 1);
|
||||||
|
|
||||||
if (detectError) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if checksum is used */
|
/* check if checksum is used */
|
||||||
{ BYTE const frameHeaderDescriptor = headerBuffer[4];
|
{ BYTE const frameHeaderDescriptor = headerBuffer[4];
|
||||||
int const contentChecksumFlag = (frameHeaderDescriptor & (1 << 2)) >> 2;
|
int const contentChecksumFlag = (frameHeaderDescriptor & (1 << 2)) >> 2;
|
||||||
if (contentChecksumFlag) {
|
if (contentChecksumFlag) {
|
||||||
int const ret = fseek(srcFile, 4, SEEK_CUR);
|
|
||||||
info->usesCheck = 1;
|
info->usesCheck = 1;
|
||||||
if (ret != 0) {
|
EXIT_IF(fseek(srcFile, 4, SEEK_CUR) != 0,
|
||||||
DISPLAY("Error: could not skip past checksum\n");
|
info_frame_error, "Error: could not skip past checksum");
|
||||||
detectError = 1;
|
} }
|
||||||
break;
|
|
||||||
} } }
|
|
||||||
info->numActualFrames++;
|
info->numActualFrames++;
|
||||||
}
|
}
|
||||||
/* Skippable frame */
|
/* Skippable frame */
|
||||||
else if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
else if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||||
U32 const frameSize = MEM_readLE32(headerBuffer + 4);
|
U32 const frameSize = MEM_readLE32(headerBuffer + 4);
|
||||||
long const seek = (long)(8 + frameSize - numBytesRead);
|
long const seek = (long)(8 + frameSize - numBytesRead);
|
||||||
int const ret = LONG_SEEK(srcFile, seek, SEEK_CUR);
|
EXIT_IF(LONG_SEEK(srcFile, seek, SEEK_CUR) != 0,
|
||||||
if (ret != 0) {
|
info_frame_error, "Error: could not find end of skippable frame");
|
||||||
DISPLAY("Error: could not find end of skippable frame\n");
|
|
||||||
detectError = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
info->numSkippableFrames++;
|
info->numSkippableFrames++;
|
||||||
}
|
}
|
||||||
/* unknown content */
|
/* unknown content */
|
||||||
else {
|
else {
|
||||||
detectError = 2;
|
return info_not_zstd;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
} /* magic number analysis */
|
||||||
} /* end analyzing frame */
|
} /* end analyzing frames */
|
||||||
fclose(srcFile);
|
return info_success;
|
||||||
info->nbFiles = 1;
|
|
||||||
return detectError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getFileInfo(fileInfo_t* info, const char* srcFileName)
|
|
||||||
|
static InfoError
|
||||||
|
getFileInfo_fileConfirmed(fileInfo_t* info, const char* inFileName)
|
||||||
{
|
{
|
||||||
int const isAFile = UTIL_isRegularFile(srcFileName);
|
InfoError status;
|
||||||
if (!isAFile) {
|
FILE* const srcFile = FIO_openSrcFile(inFileName);
|
||||||
DISPLAY("Error : %s is not a file", srcFileName);
|
EXIT_IF(srcFile == NULL, info_file_error, "Error: could not open source file %s", inFileName);
|
||||||
return 3;
|
|
||||||
|
info->compressedSize = UTIL_getFileSize(inFileName);
|
||||||
|
status = FIO_analyzeFrames(info, srcFile);
|
||||||
|
|
||||||
|
fclose(srcFile);
|
||||||
|
info->nbFiles = 1;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** getFileInfo() :
|
||||||
|
* Reads information from file, stores in *info
|
||||||
|
* @return : InfoError status
|
||||||
|
*/
|
||||||
|
static InfoError
|
||||||
|
getFileInfo(fileInfo_t* info, const char* srcFileName)
|
||||||
|
{
|
||||||
|
EXIT_IF(!UTIL_isRegularFile(srcFileName),
|
||||||
|
info_file_error, "Error : %s is not a file", srcFileName);
|
||||||
return getFileInfo_fileConfirmed(info, srcFileName);
|
return getFileInfo_fileConfirmed(info, srcFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void displayInfo(const char* inFileName, const fileInfo_t* info, int displayLevel){
|
static void
|
||||||
|
displayInfo(const char* inFileName, const fileInfo_t* info, int displayLevel)
|
||||||
|
{
|
||||||
unsigned const unit = info->compressedSize < (1 MB) ? (1 KB) : (1 MB);
|
unsigned const unit = info->compressedSize < (1 MB) ? (1 KB) : (1 MB);
|
||||||
const char* const unitStr = info->compressedSize < (1 MB) ? "KB" : "MB";
|
const char* const unitStr = info->compressedSize < (1 MB) ? "KB" : "MB";
|
||||||
double const windowSizeUnit = (double)info->windowSize / unit;
|
double const windowSizeUnit = (double)info->windowSize / unit;
|
||||||
@ -2197,43 +2175,45 @@ static fileInfo_t FIO_addFInfo(fileInfo_t fi1, fileInfo_t fi2)
|
|||||||
static int FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel){
|
static int FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel){
|
||||||
fileInfo_t info;
|
fileInfo_t info;
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
{ int const error = getFileInfo(&info, inFileName);
|
{ InfoError const error = getFileInfo(&info, inFileName);
|
||||||
if (error == 1) {
|
if (error == info_frame_error) {
|
||||||
/* display error, but provide output */
|
/* display error, but provide output */
|
||||||
DISPLAY("An error occurred while getting file info \n");
|
DISPLAYLEVEL(1, "Error while parsing %s \n", inFileName);
|
||||||
}
|
}
|
||||||
else if (error == 2) {
|
else if (error == info_not_zstd) {
|
||||||
DISPLAYOUT("File %s not compressed by zstd \n", inFileName);
|
DISPLAYOUT("File %s not compressed by zstd \n", inFileName);
|
||||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (error == 3) {
|
else if (error == info_file_error) {
|
||||||
/* error occurred while opening the file */
|
/* error occurred while opening the file */
|
||||||
if (displayLevel > 2) DISPLAYOUT("\n");
|
if (displayLevel > 2) DISPLAYOUT("\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
displayInfo(inFileName, &info, displayLevel);
|
displayInfo(inFileName, &info, displayLevel);
|
||||||
*total = FIO_addFInfo(*total, info);
|
*total = FIO_addFInfo(*total, info);
|
||||||
|
assert(error>=0 || error<=1);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel){
|
int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int displayLevel)
|
||||||
unsigned u;
|
{
|
||||||
|
/* ensure no specified input is stdin (needs fseek() capability) */
|
||||||
|
{ unsigned u;
|
||||||
for (u=0; u<numFiles;u++) {
|
for (u=0; u<numFiles;u++) {
|
||||||
if (!strcmp (filenameTable[u], stdinmark)) {
|
EXIT_IF(!strcmp (filenameTable[u], stdinmark),
|
||||||
DISPLAYOUT("zstd: --list does not support reading from standard input\n");
|
1, "zstd: --list does not support reading from standard input");
|
||||||
return 1;
|
} }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numFiles == 0) {
|
if (numFiles == 0) {
|
||||||
if (!IS_CONSOLE(stdin)) {
|
if (!IS_CONSOLE(stdin)) {
|
||||||
DISPLAYOUT("zstd: --list does not support reading from standard input\n");
|
DISPLAYLEVEL(1, "zstd: --list does not support reading from standard input \n");
|
||||||
}
|
}
|
||||||
DISPLAYOUT("No files given\n");
|
DISPLAYLEVEL(1, "No files given \n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayLevel <= 2) {
|
if (displayLevel <= 2) {
|
||||||
DISPLAYOUT("Frames Skips Compressed Uncompressed Ratio Check Filename\n");
|
DISPLAYOUT("Frames Skips Compressed Uncompressed Ratio Check Filename\n");
|
||||||
}
|
}
|
||||||
@ -2241,9 +2221,11 @@ int FIO_listMultipleFiles(unsigned numFiles, const char** filenameTable, int dis
|
|||||||
fileInfo_t total;
|
fileInfo_t total;
|
||||||
memset(&total, 0, sizeof(total));
|
memset(&total, 0, sizeof(total));
|
||||||
total.usesCheck = 1;
|
total.usesCheck = 1;
|
||||||
|
/* --list each file, and check for any error */
|
||||||
|
{ unsigned u;
|
||||||
for (u=0; u<numFiles;u++) {
|
for (u=0; u<numFiles;u++) {
|
||||||
error |= FIO_listFile(&total, filenameTable[u], displayLevel);
|
error |= FIO_listFile(&total, filenameTable[u], displayLevel);
|
||||||
}
|
} }
|
||||||
if (numFiles > 1 && displayLevel <= 2) { /* display total */
|
if (numFiles > 1 && displayLevel <= 2) { /* display total */
|
||||||
unsigned const unit = total.compressedSize < (1 MB) ? (1 KB) : (1 MB);
|
unsigned const unit = total.compressedSize < (1 MB) ? (1 KB) : (1 MB);
|
||||||
const char* const unitStr = total.compressedSize < (1 MB) ? "KB" : "MB";
|
const char* const unitStr = total.compressedSize < (1 MB) ? "KB" : "MB";
|
||||||
|
|||||||
@ -180,6 +180,8 @@ chmod 400 tmpro.zst
|
|||||||
$ZSTD -q tmpro && die "should have refused to overwrite read-only file"
|
$ZSTD -q tmpro && die "should have refused to overwrite read-only file"
|
||||||
$ZSTD -q -f tmpro
|
$ZSTD -q -f tmpro
|
||||||
rm -f tmpro tmpro.zst
|
rm -f tmpro tmpro.zst
|
||||||
|
|
||||||
|
|
||||||
$ECHO "test : file removal"
|
$ECHO "test : file removal"
|
||||||
$ZSTD -f --rm tmp
|
$ZSTD -f --rm tmp
|
||||||
test ! -f tmp # tmp should no longer be present
|
test ! -f tmp # tmp should no longer be present
|
||||||
@ -196,9 +198,14 @@ $ECHO a | $ZSTD --rm > $INTOVOID # --rm should remain silent
|
|||||||
rm tmp
|
rm tmp
|
||||||
$ZSTD -f tmp && die "tmp not present : should have failed"
|
$ZSTD -f tmp && die "tmp not present : should have failed"
|
||||||
test ! -f tmp.zst # tmp.zst should not be created
|
test ! -f tmp.zst # tmp.zst should not be created
|
||||||
|
$ECHO "test : do not delete destination when source is not present"
|
||||||
|
touch tmp # create destination file
|
||||||
|
$ZSTD -d -f tmp.zst && die "attempt to decompress a non existing file"
|
||||||
|
! test -f tmp # destination file should still be present (test disabled temporarily)
|
||||||
|
rm tmp*
|
||||||
|
|
||||||
|
|
||||||
$ECHO "test : compress multiple files"
|
$ECHO "test : compress multiple files"
|
||||||
rm tmp*
|
|
||||||
$ECHO hello > tmp1
|
$ECHO hello > tmp1
|
||||||
$ECHO world > tmp2
|
$ECHO world > tmp2
|
||||||
$ZSTD tmp1 tmp2 -o "$INTOVOID"
|
$ZSTD tmp1 tmp2 -o "$INTOVOID"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user