mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-08 19:32:39 +08:00
137 lines
6.2 KiB
C++
137 lines
6.2 KiB
C++
|
|
#ifndef ZIPFILE_H
|
|
#define ZIPFILE_H
|
|
|
|
#include <stdint.h>
|
|
|
|
extern "C" {
|
|
#include "zipcrc.h"
|
|
}
|
|
|
|
#include <map>
|
|
|
|
#pragma pack(push,1)
|
|
struct ZIPLocalFileHeader { /* ZIP File Format Specification v6.3.4 sec 4.3.7 Local file header */
|
|
uint32_t local_file_header_signature; /* +0x00 0x04034b50 */
|
|
uint16_t version_needed_to_extract; /* +0x04 */
|
|
uint16_t general_purpose_bit_flag; /* +0x06 */
|
|
uint16_t compression_method; /* +0x08 */
|
|
uint16_t last_mod_file_time; /* +0x0A */
|
|
uint16_t last_mod_file_date; /* +0x0C */
|
|
uint32_t crc_32; /* +0x0E */
|
|
uint32_t compressed_size; /* +0x12 */
|
|
uint32_t uncompressed_size; /* +0x16 */
|
|
uint16_t file_name_length; /* +0x1A */
|
|
uint16_t extra_field_length; /* +0x1C */
|
|
}; /* =0x1E */
|
|
#pragma pack(pop)
|
|
|
|
#pragma pack(push,1)
|
|
# define PKZIP_CENTRAL_DIRECTORY_HEADER_SIG (0x02014B50UL)
|
|
|
|
struct pkzip_central_directory_header_main { /* PKZIP APPNOTE 2.0: General Format of a ZIP file section C */
|
|
uint32_t sig; /* 4 bytes +0x00 0x02014B50 = 'PK\x01\x02' */
|
|
uint16_t version_made_by; /* 2 bytes +0x04 version made by */
|
|
uint16_t version_needed_to_extract; /* 2 bytes +0x06 version needed to extract */
|
|
uint16_t general_purpose_bit_flag; /* 2 bytes +0x08 general purpose bit flag */
|
|
uint16_t compression_method; /* 2 bytes +0x0A compression method */
|
|
uint16_t last_mod_file_time; /* 2 bytes +0x0C */
|
|
uint16_t last_mod_file_date; /* 2 bytes +0x0E */
|
|
uint32_t crc32; /* 4 bytes +0x10 */
|
|
uint32_t compressed_size; /* 4 bytes +0x14 */
|
|
uint32_t uncompressed_size; /* 4 bytes +0x18 */
|
|
uint16_t filename_length; /* 2 bytes +0x1C */
|
|
uint16_t extra_field_length; /* 2 bytes +0x1E */
|
|
uint16_t file_comment_length; /* 2 bytes +0x20 */
|
|
uint16_t disk_number_start; /* 2 bytes +0x22 */
|
|
uint16_t internal_file_attributes; /* 2 bytes +0x24 */
|
|
uint32_t external_file_attributes; /* 4 bytes +0x26 */
|
|
uint32_t relative_offset_of_local_header;/* 4 bytes +0x2A */
|
|
}; /* =0x2E */
|
|
/* filename and extra field follow, then file data */
|
|
#pragma pack(pop)
|
|
|
|
#pragma pack(push,1)
|
|
# define PKZIP_CENTRAL_DIRECTORY_END_SIG (0x06054B50UL)
|
|
|
|
struct pkzip_central_directory_header_end { /* PKZIP APPNOTE 2.0: General Format of a ZIP file section C */
|
|
uint32_t sig; /* 4 bytes +0x00 0x06054B50 = 'PK\x05\x06' */
|
|
uint16_t number_of_this_disk; /* 2 bytes +0x04 */
|
|
uint16_t number_of_disk_with_start_of_central_directory;
|
|
/* 2 bytes +0x06 */
|
|
uint16_t total_number_of_entries_of_central_dir_on_this_disk;
|
|
/* 2 bytes +0x08 */
|
|
uint16_t total_number_of_entries_of_central_dir;
|
|
/* 2 bytes +0x0A */
|
|
uint32_t size_of_central_directory; /* 4 bytes +0x0C */
|
|
uint32_t offset_of_central_directory_from_start_disk;
|
|
/* 4 bytes +0x10 */
|
|
uint16_t zipfile_comment_length; /* 2 bytes +0x14 */
|
|
}; /* =0x16 */
|
|
/* filename and extra field follow, then file data */
|
|
#pragma pack(pop)
|
|
|
|
class ZIPFile;
|
|
|
|
class ZIPFileEntry {
|
|
public:
|
|
bool can_write = false;
|
|
off_t file_length = 0;
|
|
off_t file_offset = 0;
|
|
off_t file_header_offset = 0;
|
|
off_t position = 0;
|
|
std::string name;
|
|
ZIPFile* file = NULL;
|
|
zipcrc_t write_crc = 0;
|
|
public:
|
|
bool rewind(void);
|
|
int read(void *buffer,size_t count);
|
|
int write(const void *buffer,size_t count);
|
|
private: /* encourage code that uses this C++ class to stream-read so that
|
|
this code can add deflate compression support later without pain and hacks */
|
|
off_t seek_file(off_t pos);
|
|
};
|
|
|
|
class ZIPFile {
|
|
public:
|
|
int file_fd = -1;
|
|
std::string filename;
|
|
std::map<std::string,ZIPFileEntry> entries;
|
|
off_t write_pos = 0;
|
|
bool can_write = false;
|
|
bool wrote_trailer = false;
|
|
std::string current_entry; /* currently writing entry */
|
|
public:
|
|
ZIPFile();
|
|
~ZIPFile();
|
|
public:
|
|
void close(void);
|
|
ZIPFileEntry *get_entry(const char *name);
|
|
ZIPFileEntry *new_entry(const char *name);
|
|
off_t end_of_file(void);
|
|
void close_current(void);
|
|
int open(const char *path,int mode);
|
|
off_t seek_file(off_t pos);
|
|
int read(void *buffer,size_t count);
|
|
int write(const void *buffer,size_t count);
|
|
void writeZIPFooter(void);
|
|
};
|
|
|
|
class zip_nv_pair_map : public std::map<std::string, std::string> {
|
|
public:
|
|
zip_nv_pair_map();
|
|
zip_nv_pair_map(ZIPFileEntry &ent);
|
|
public:
|
|
std::string &get(const char *name);
|
|
bool get_bool(const char *name);
|
|
long get_long(const char *name);
|
|
unsigned long get_ulong(const char *name);
|
|
void process_line(char *line/*will modify, assume caller has put NUL at the end*/);
|
|
void read_nv_pairs(ZIPFileEntry &ent);
|
|
};
|
|
|
|
void zip_nv_write(ZIPFileEntry &ent,const char *name,bool val);
|
|
void zip_nv_write(ZIPFileEntry &ent,const char *name,long val);
|
|
void zip_nv_write_hex(ZIPFileEntry &ent,const char *name,unsigned long val);
|
|
#endif //ZIPFILE_H
|