#include #include #include #include "ZipDefine.h" #include "CRC.h" #define TARGET_FILE_NAME "MyZip.txt" bool ZipArchiver(); uint32_t getCRC32(const uint8_t* pData, size_t length); int main() { std::printf("==================== Hello Zip! ====================\r\n"); int iRet = 0; // Zip Format define check size_t iSizeTest = sizeof(LocalFileHeader); if (LOCAL_FILE_HEADER_BYTE != iSizeTest) { std::printf("1 Wrong Header Size : %zu / %d \r\n", iSizeTest, LOCAL_FILE_HEADER_BYTE); iRet = -1; } iSizeTest = sizeof(CentralDirectory); if (CENTRAL_DIRECTORY_BYTE != iSizeTest) { std::printf("2 Wrong Header Size : %zu / %d \r\n", iSizeTest, CENTRAL_DIRECTORY_BYTE); iRet = -1; } iSizeTest = sizeof(EoCDRecord); if (EOCD_BYTE != iSizeTest) { std::printf("3 Wrong Header Size : %zu / %d \r\n", iSizeTest, EOCD_BYTE); iRet = -1; } // Main Zip archive method if (iRet != -1) { if(!ZipArchiver()) { iRet = -1; } } return iRet; } bool ZipArchiver() { LocalFileHeader LFHeader = {}; CentralDirectory CentDir = {}; EoCDRecord EOCDR = {}; using namespace std; ifstream fileIn(TARGET_FILE_NAME, ios::binary); bool iRet = fileIn.is_open(); if (!iRet) { printf("File open failed"); } else { // 파일 크기 계산 // seekg(offset, 목표점) fileIn.seekg(0, ios::end); streamsize fileInSize = fileIn.tellg(); // beg == begin fileIn.seekg(0, ios::beg); // TODO : Buffering 으로 구현. 현재는 파일 통짜로 읽음. // 메모리 할당 uint8_t* pFile = (uint8_t *)malloc(fileInSize); // Read fileIn.read((char *)pFile, fileInSize); // ZIP 포맷 채워넣기 { // Get CRC value // TODO : streamsize 와 size_t 의 mismatch (long long <-> unsigned long long) uint32_t myCRC = getCRC32(pFile, fileInSize); // Put PK Signature LFHeader.signature = PK_SIGNATURE_LF_HEADER; CentDir.signature = PK_SIGNATURE_CENT_DIR; EOCDR.signature = PK_SIGNATURE_EO_CDR; // TOOD : versionMadeBy (Only CentDir) // TODO : versionNeededToExtract // TODO : generalBitFlag // Put compressed method (uncompressed) LFHeader.compressionMethod = METHOD_UNCOMPRESSED; CentDir.compressionMethod = METHOD_UNCOMPRESSED; // TODO : lastMode[Time|Date] // Put CRC value LFHeader.crc32 = myCRC; CentDir.crc32 = myCRC; // Put File size LFHeader.sizeOfUncompressed = (uint32_t)fileInSize; CentDir.sizeOfUncompressed = (uint32_t)fileInSize; LFHeader.sizeOfCompressed = LFHeader.sizeOfUncompressed; CentDir.sizeOfCompressed = CentDir.sizeOfUncompressed; // Put File name length uint16_t fileNameLeng = strlen(TARGET_FILE_NAME); LFHeader.lengthOfFileName = fileNameLeng; CentDir.lengthOfFileName = fileNameLeng; // Extra Field 는 사용하지 않음 // LFHeader.lengthOfExtraField = NOT_USED; // CentDir.lengthOfExtraField = NOT_USED; // TODO : CentDir 나머지 format // - lengthOfFileComment // - diskNumStart; // - attributeInternal; // - attributeExternal; // - offsetLocalHeader; // TODO : EOCDR 나머지 format // - diskNumber // - diskNumber_CentralDirStart // - numOfCentralDir // - numOfEntries; // - SizeOfCentralDir; // - OffsetOfCentralDirOffset; // - LengthOfCommentLength; } // Free free(pFile); } return iRet; } uint32_t getCRC32(const uint8_t* pData, size_t length) { uint32_t crc = 0xFFFFFFFF; // 1. 입력 for (size_t i = 0; i < length ; i++) { // Index 추출 // 입력과 현재 CRC를 1 Byte 씩 XOR + (1의 보수처리) uint8_t iTableIdx = (crc ^ pData[i]) & 0xFF; // 1 Byte Shift crc = crc >> 8; // Table 과 XOR 계산 crc = crc ^ crcTable[iTableIdx]; } // TODO : CRC 최적화 // "_mm_crc32_u16" => MSVC 자체적으로 지원하는 최적화된 CRC 가 있는듯? // 1의 보수처리 return crc ^ 0xFFFFFFFF; }