- unsigned short version; /* 0-1 */
- unsigned short flags; /* 2-3 */
- unsigned short method; /* 4-5 */
- unsigned short modtime; /* 6-7 */
- unsigned short moddate; /* 8-9 */
- unsigned int crc32 ATTRIBUTE_PACKED; /* 10-13 */
- unsigned int cmpsize ATTRIBUTE_PACKED; /* 14-17 */
- unsigned int ucmpsize ATTRIBUTE_PACKED; /* 18-21 */
- unsigned short filename_len; /* 22-23 */
- unsigned short extra_len; /* 24-25 */
- } formatted ATTRIBUTE_PACKED;
-} zip_header_t;
-
-static void unzip_skip(int fd, off_t skip)
+ /* uint32_t signature; 50 4b 01 02 */
+ uint16_t version_made_by; /* 0-1 */
+ uint16_t version_needed; /* 2-3 */
+ uint16_t cdf_flags; /* 4-5 */
+ uint16_t method; /* 6-7 */
+ uint16_t mtime; /* 8-9 */
+ uint16_t mdate; /* 10-11 */
+ uint32_t crc32; /* 12-15 */
+ uint32_t cmpsize; /* 16-19 */
+ uint32_t ucmpsize; /* 20-23 */
+ uint16_t file_name_length; /* 24-25 */
+ uint16_t extra_field_length; /* 26-27 */
+ uint16_t file_comment_length; /* 28-29 */
+ uint16_t disk_number_start; /* 30-31 */
+ uint16_t internal_file_attributes; /* 32-33 */
+ uint32_t external_file_attributes PACKED; /* 34-37 */
+ uint32_t relative_offset_of_local_header PACKED; /* 38-41 */
+ } formatted PACKED;
+} cdf_header_t;
+
+struct BUG_cdf_header_must_be_42_bytes {
+ char BUG_cdf_header_must_be_42_bytes[
+ offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4
+ == CDF_HEADER_LEN ? 1 : -1];
+};
+
+#define FIX_ENDIANNESS_CDF(cdf_header) do { \
+ (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \
+ (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \
+ (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \
+ (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \
+ (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \
+ (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \
+ IF_DESKTOP( \
+ (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \
+ (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \
+ ) \
+} while (0)
+
+#define CDE_HEADER_LEN 16
+
+typedef union {
+ uint8_t raw[CDE_HEADER_LEN];
+ struct {
+ /* uint32_t signature; 50 4b 05 06 */
+ uint16_t this_disk_no;
+ uint16_t disk_with_cdf_no;
+ uint16_t cdf_entries_on_this_disk;
+ uint16_t cdf_entries_total;
+ uint32_t cdf_size;
+ uint32_t cdf_offset;
+ /* uint16_t file_comment_length; */
+ /* .ZIP file comment (variable size) */
+ } formatted PACKED;
+} cde_header_t;
+
+struct BUG_cde_header_must_be_16_bytes {
+ char BUG_cde_header_must_be_16_bytes[
+ sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1];
+};
+
+#define FIX_ENDIANNESS_CDE(cde_header) do { \
+ (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \
+} while (0)
+
+enum { zip_fd = 3 };
+
+
+#if ENABLE_DESKTOP
+
+#define PEEK_FROM_END 16384
+
+/* NB: does not preserve file position! */
+static uint32_t find_cdf_offset(void)