From f175be393874e7cbf66479412a57cc148d68c553 Mon Sep 17 00:00:00 2001 From: Juno Kim Date: Fri, 7 Aug 2026 07:58:28 +0900 Subject: [PATCH] add Zip format Define.h --- Define.h | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++ MyZip.vcxproj | 5 +- main.cpp | 42 ++++++++++++- 3 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 Define.h diff --git a/Define.h b/Define.h new file mode 100644 index 0000000..fcf3c40 --- /dev/null +++ b/Define.h @@ -0,0 +1,161 @@ +#pragma once + +#include + +/** Overall .ZIP file format: + + [local file header 1] -> "PK" + 0x4b50 + ... + [encryption header 1] + [file data 1] + [data descriptor 1] + . + . + . + [local file header n] -> "PK" + 0x4b50 + ... + [encryption header n] + [file data n] + [data descriptor n] + [archive decryption header] + [archive extra data record] + [central directory header 1] + . + . + . + [central directory header n] -> "PK" + 0x4b50 + [zip64 end of central directory record] + [zip64 end of central directory locator] + [end of central directory record] <- 필수 포함 (단 한개) +*/ + +/** Local file header: + + local file header signature 4 bytes (0x04034b50) + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + file name length 2 bytes -> Variable + extra field length 2 bytes -> Variable + + file name (variable size) + extra field (variable size) + */ + +#pragma pack(push, 1) +constexpr int LOCAL_FILE_HEADER_BYTE = 30; + + struct LocalFileHeader { + uint32_t signature; + uint16_t versionNeededToExtract; + uint16_t generalBitFlag; + uint16_t compressionMethod; // no compression == 0 + uint16_t lastModTime; // 압축 시점의 시간 (1980년 기준 시간) + uint16_t lastModDate; // 압축 시점의 날짜 (1980년 기준 연도) + uint32_t crc32; + uint32_t compressedSize; // same as unCompression (cuz no compreesion) + uint32_t unCompressedSize; + uint16_t fileNameLength; + uint16_t extraFieldLength; + + // var[fileNameLength] fileName + // var[extraFieldLength] extraField + }; + +/** Central directory structure: + + [central directory header 1] + . + . + . + [central directory header n] + [digital signature] + + File header: + + central file header signature 4 bytes (0x02014b50) + version made by 2 bytes + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + file name length 2 bytes + extra field length 2 bytes + file comment length 2 bytes + disk number start 2 bytes + internal file attributes 2 bytes + external file attributes 4 bytes + relative offset of local header 4 bytes + + file name (variable size) + extra field (variable size) + file comment (variable size) + */ + + constexpr int CENTRAL_DIRECTORY_BYTE = 46; + struct CentralDirectory { + + uint32_t signature; + uint16_t versionMadeBy; + uint16_t versionNeededToExtract; + uint16_t generalBitFlag; + uint16_t compressionMethod; // no compression == 0 + uint16_t lastModTime; // 압축 시점의 시간 (1980년 기준 시간) + uint16_t lastModDate; // 압축 시점의 날짜 (1980년 기준 연도) + uint32_t crc32; + uint32_t compressedSize; // same as unCompression (cuz no compreesion) + uint32_t unCompressedSize; + uint16_t fileNameLength; + uint16_t extraFieldLength; + uint16_t fileCommentLength; + + uint16_t diskNumStart; + uint16_t attributeInternal; + uint32_t attributeExternal; + uint32_t offsetLocalHeader; + + // var[fileNameLength] fileName + // var[extraFieldLength] extraField + // var[fileCommentLength] fileComment +}; + + /** End of central directory record: + + end of central dir signature 4 bytes (0x0605 + 4b50) + number of this disk 2 bytes + number of the disk with the + start of the central directory 2 bytes + total number of entries in the + central directory on this disk 2 bytes + total number of entries in + the central directory 2 bytes + size of the central directory 4 bytes + offset of start of central + directory with respect to + the starting disk number 4 bytes + .ZIP file comment length 2 bytes + .ZIP file comment (variable size) +*/ + constexpr int EOCD_BYTE = 22; + + struct EoCDRecord { + uint32_t signature; + uint16_t diskNumber; + uint16_t diskNumber_CentralDirectoryStart; + uint16_t numOfCentralDirectory; // TODO : 이름 애매함. + uint16_t numEntries; // TODO : 이름 애매함. + uint32_t centralDirectorySize; + uint32_t centralDirectoryOffset; + uint16_t zipFileCommentLength; + + // var[zipFileCommentLength] zipFileComment +}; + +#pragma pack(pop) diff --git a/MyZip.vcxproj b/MyZip.vcxproj index 3a71371..c641251 100644 --- a/MyZip.vcxproj +++ b/MyZip.vcxproj @@ -1,4 +1,4 @@ - + @@ -125,6 +125,9 @@ + + + diff --git a/main.cpp b/main.cpp index c493a39..17c052a 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,46 @@ #include +#include "Define.h" + +void Zipper(); int main() { - std::printf("Hello Zip! \r\n"); + std::printf("==================== Hello Zip! ====================\r\n"); + + int iRet = 0; + + int iSizeTest = sizeof(LocalFileHeader); + if (LOCAL_FILE_HEADER_BYTE != iSizeTest) + { + std::printf("1 Wrong Header Size : %d / %d \r\n", iSizeTest, LOCAL_FILE_HEADER_BYTE); + iRet = -1; + } + iSizeTest = sizeof(CentralDirectory); + if (CENTRAL_DIRECTORY_BYTE != iSizeTest) + { + std::printf("2 Wrong Header Size : %d / %d \r\n", iSizeTest, CENTRAL_DIRECTORY_BYTE); + iRet = -1; + } + iSizeTest = sizeof(EoCDRecord); + if (EOCD_BYTE != iSizeTest) + { + std::printf("3 Wrong Header Size : %d / %d \r\n", iSizeTest, EOCD_BYTE); + iRet = -1; + } + + if (iRet != -1) + { + Zipper(); + } + + return 0; +} + +void Zipper() +{ + LocalFileHeader LFHeader; + CentralDirectory CentDirec; + EoCDRecord ECDR; + + } \ No newline at end of file