in aios/filesystem/fslib/tools/fsutil/FsUtil.cpp [527:663]
ErrorCode FsUtil::runDecryptZCat(const char *srcPath, const char *cipherOption, bool optionUseBase64) {
autil::cipher::CipherOption option(autil::cipher::CipherType::CT_UNKNOWN);
if (cipherOption == nullptr) {
if (!getCipherOption(option)) {
return EC_BADARGS;
}
} else {
if (!option.fromKVString(cipherOption, optionUseBase64)) {
return EC_BADARGS;
}
}
FileMeta fileMeta;
ErrorCode ret = FileSystem::getFileMeta(srcPath, fileMeta);
if (ret != EC_OK) {
cerr << "fail to get length of file <" << srcPath << ">. " << FileSystem::getErrorString(ret) << endl;
return ret;
}
unique_ptr<File> rFile(FileSystem::openFile(srcPath, READ));
if (!rFile->isOpened()) {
cerr << "open file <" << srcPath << "> for read fail. " << FileSystem::getErrorString(rFile->getLastError())
<< endl;
return rFile->getLastError();
}
volatile bool hasError = false;
ErrorCode rCode = EC_OK;
auto decrypter = autil::cipher::AESCipherCreator::createStreamDecrypter(option, 2 * 1024 * 1024 /* 2 MB */);
if (decrypter == nullptr) {
cerr << "create stream decrypter fail." << endl;
return EC_UNKNOWN;
}
size_t totalDecryptLen = 0;
std::thread readThread([&]() {
size_t bufferLen = 2 * 1024 * 1024;
SafeBuffer buffer(bufferLen);
while (!hasError) {
auto readLen = rFile->read(buffer.getBuffer(), bufferLen);
if (readLen < 0) {
cerr << "read file <" << srcPath << "> fail. " << FileSystem::getErrorString(rFile->getLastError())
<< endl;
rCode = rFile->getLastError();
hasError = true;
continue;
}
if (readLen > 0) {
if (!decrypter->append((const unsigned char *)buffer.getBuffer(), readLen)) {
cerr << "decrypter append data fail." << endl;
rCode = EC_UNKNOWN;
hasError = true;
continue;
}
}
totalDecryptLen += readLen;
if (rFile->isEof()) {
break;
}
}
if (!decrypter->seal()) {
cerr << "decrypter seal fail." << endl;
rCode = EC_UNKNOWN;
hasError = true;
}
});
ErrorCode wCode = EC_OK;
std::thread writeThread([&]() {
std::unique_ptr<AESCipherDataReader> reader(new AESCipherDataReader(decrypter, hasError));
if (!GZipHeaderParser<AESCipherDataReader>::parse(reader)) {
hasError = true;
wCode = EC_UNKNOWN;
return;
}
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
cerr << "gzip infalte init error" << endl;
hasError = true;
wCode = EC_UNKNOWN;
return;
}
size_t bufferLen = 2 * 1024 * 1024;
SafeBuffer buffer(bufferLen + 1);
SafeBuffer outBuffer(bufferLen);
while (true) {
auto readLen = reader->read(buffer.getBuffer(), bufferLen);
if (readLen < 0) {
cerr << "read decrypted file data fail. " << endl;
inflateEnd(&strm);
hasError = true;
wCode = EC_UNKNOWN;
return;
}
if (readLen > 0) {
char *inBuf = buffer.getBuffer();
char *outBuf = outBuffer.getBuffer();
inBuf[readLen] = 0;
uint32_t bufferNow = 0;
uint32_t bufferEnd = readLen;
while (bufferNow < bufferEnd) {
strm.avail_out = bufferLen;
strm.next_out = (Bytef *)outBuf;
strm.avail_in = bufferEnd - bufferNow;
strm.next_in = (Bytef *)&inBuf[bufferNow];
int ret = inflate(&strm, Z_NO_FLUSH);
if ((ret != Z_STREAM_END) && (ret != Z_OK)) {
cerr << "infalte error(" << ret << ")" << endl;
inflateEnd(&strm);
hasError = true;
wCode = EC_UNKNOWN;
return;
}
bufferNow = bufferEnd - strm.avail_in;
auto dSize = bufferLen - strm.avail_out;
fwrite(outBuf, sizeof(char), dSize, stdout);
if (ret == Z_STREAM_END) {
inflateEnd(&strm);
return;
}
}
}
if (reader->isEof()) {
break;
}
}
inflateEnd(&strm);
});
readThread.join();
writeThread.join();
if (hasError) {
return rCode != EC_OK ? rCode : wCode;
}
return EC_OK;
}