extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* fileOutTmp, uLong* nRecovered, uLong* bytesRecovered) { int err = Z_OK; FILE* fpZip = fopen(file, "rb"); FILE* fpOut = fopen(fileOut, "wb"); FILE* fpOutCD = fopen(fileOutTmp, "wb"); if (fpZip != NULL && fpOut != NULL) { int entries = 0; uLong totalBytes = 0; char header[30]; char filename[256]; char extra[1024]; int offset = 0; int offsetCD = 0; while ( fread(header, 1, 30, fpZip) == 30 ) { int currentOffset = offset; /* File entry */ if (READ_32(header) == 0x04034b50) { unsigned int version = READ_16(header + 4); unsigned int gpflag = READ_16(header + 6); unsigned int method = READ_16(header + 8); unsigned int filetime = READ_16(header + 10); unsigned int filedate = READ_16(header + 12); unsigned int crc = READ_32(header + 14); /* crc */ unsigned int cpsize = READ_32(header + 18); /* compressed size */ unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ unsigned int fnsize = READ_16(header + 26); /* file name length */ unsigned int extsize = READ_16(header + 28); /* extra field length */ filename[0] = extra[0] = '\0'; /* Header */ if (fwrite(header, 1, 30, fpOut) == 30) { offset += 30; } else { err = Z_ERRNO; break; } /* Filename */ if (fnsize > 0) { if (fread(filename, 1, fnsize, fpZip) == fnsize) { if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { offset += fnsize; } else { err = Z_ERRNO; break; } } else { err = Z_ERRNO; break; } } else { err = Z_STREAM_ERROR; break; } /* Extra field */ if (extsize > 0) { if (fread(extra, 1, extsize, fpZip) == extsize) { if (fwrite(extra, 1, extsize, fpOut) == extsize) { offset += extsize; } else { err = Z_ERRNO; break; } } else { err = Z_ERRNO; break; } } /* Data */ { int dataSize = cpsize; if (dataSize == 0) { dataSize = uncpsize; } if (dataSize > 0) { char* data = (char*)malloc(dataSize); if (data != NULL) { if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { offset += dataSize; totalBytes += dataSize; } else { err = Z_ERRNO; } } else { err = Z_ERRNO; } free(data); if (err != Z_OK) { break; } } else { err = Z_MEM_ERROR; break; } } } /* Central directory entry */ { char header[46]; char* comment = ""; int comsize = (int) strlen(comment); WRITE_32(header, 0x02014b50); WRITE_16(header + 4, version); WRITE_16(header + 6, version); WRITE_16(header + 8, gpflag); WRITE_16(header + 10, method); WRITE_16(header + 12, filetime); WRITE_16(header + 14, filedate); WRITE_32(header + 16, crc); WRITE_32(header + 20, cpsize); WRITE_32(header + 24, uncpsize); WRITE_16(header + 28, fnsize); WRITE_16(header + 30, extsize); WRITE_16(header + 32, comsize); WRITE_16(header + 34, 0); /* disk # */ WRITE_16(header + 36, 0); /* int attrb */ WRITE_32(header + 38, 0); /* ext attrb */ WRITE_32(header + 42, currentOffset); /* Header */ if (fwrite(header, 1, 46, fpOutCD) == 46) { offsetCD += 46; /* Filename */ if (fnsize > 0) { if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { offsetCD += fnsize; } else { err = Z_ERRNO; break; } } else { err = Z_STREAM_ERROR; break; } /* Extra field */ if (extsize > 0) { if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { offsetCD += extsize; } else { err = Z_ERRNO; break; } } /* Comment field */ if (comsize > 0) { if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { offsetCD += comsize; } else { err = Z_ERRNO; break; } } } else { err = Z_ERRNO; break; } } /* Success */ entries++; } else { break; } } /* Final central directory */ { int entriesZip = entries; char header[22]; char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; int comsize = (int) strlen(comment); if (entriesZip > 0xffff) { entriesZip = 0xffff; } WRITE_32(header, 0x06054b50); WRITE_16(header + 4, 0); /* disk # */ WRITE_16(header + 6, 0); /* disk # */ WRITE_16(header + 8, entriesZip); /* hack */ WRITE_16(header + 10, entriesZip); /* hack */ WRITE_32(header + 12, offsetCD); /* size of CD */ WRITE_32(header + 16, offset); /* offset to CD */ WRITE_16(header + 20, comsize); /* comment */ /* Header */ if (fwrite(header, 1, 22, fpOutCD) == 22) { /* Comment field */ if (comsize > 0) { if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { err = Z_ERRNO; } } } else { err = Z_ERRNO; } } /* Final merge (file + central directory) */ fclose(fpOutCD); if (err == Z_OK) { fpOutCD = fopen(fileOutTmp, "rb"); if (fpOutCD != NULL) { int nRead; char buffer[8192]; while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { err = Z_ERRNO; break; } } fclose(fpOutCD); } } /* Close */ fclose(fpZip); fclose(fpOut); /* Wipe temporary file */ (void)remove(fileOutTmp); /* Number of recovered entries */ if (err == Z_OK) { if (nRecovered != NULL) { *nRecovered = entries; } if (bytesRecovered != NULL) { *bytesRecovered = totalBytes; } } } else { err = Z_STREAM_ERROR; } return err; }
#define WRITE_16(V, a, b) a = (V >> 8) & 0xFF; b = V & 0xFF; #define WRITE_32(V, a, b, c, d) a = (V >> 24) & 0xFF; b = (V >> 16) & 0xFF; c = (V >> 8) & 0xFF; d = V & 0xFF; READ_BUFFER(l_tm_buffer_read_uint8, (uint8_t) a[0]); READ_BUFFER(l_tm_buffer_read_uint16le, (uint16_t) TO_16(a[1], a[0])); READ_BUFFER(l_tm_buffer_read_uint16be, (uint16_t) TO_16(a[0], a[1])); READ_BUFFER(l_tm_buffer_read_uint32le, (uint32_t) TO_32(a[3], a[2], a[1], a[0])); READ_BUFFER(l_tm_buffer_read_uint32be, (uint32_t) TO_32(a[0], a[1], a[2], a[3])); READ_BUFFER(l_tm_buffer_read_int8, (int8_t) a[0]); READ_BUFFER(l_tm_buffer_read_int16le, (int16_t) TO_16(a[1], a[0])); READ_BUFFER(l_tm_buffer_read_int16be, (int16_t) TO_16(a[0], a[1])); READ_BUFFER(l_tm_buffer_read_int32le, (int32_t) TO_32(a[3], a[2], a[1], a[0])); READ_BUFFER(l_tm_buffer_read_int32be, (int32_t) TO_32(a[0], a[1], a[2], a[3])); WRITE_BUFFER(l_tm_buffer_write_uint8, WRITE_8((uint8_t) value, a[0])); WRITE_BUFFER(l_tm_buffer_write_uint16le, WRITE_16((uint16_t) value, a[1], a[0])); WRITE_BUFFER(l_tm_buffer_write_uint16be, WRITE_16((uint16_t) value, a[0], a[1])); WRITE_BUFFER(l_tm_buffer_write_uint32le, WRITE_32((uint32_t) value, a[3], a[2], a[1], a[0])); WRITE_BUFFER(l_tm_buffer_write_uint32be, WRITE_32((uint32_t) value, a[0], a[1], a[2], a[3])); WRITE_BUFFER(l_tm_buffer_write_int8, WRITE_8((int8_t) value, a[0])); WRITE_BUFFER(l_tm_buffer_write_int16le, WRITE_16((int16_t) value, a[1], a[0])); WRITE_BUFFER(l_tm_buffer_write_int16be, WRITE_16((int16_t) value, a[0], a[1])); WRITE_BUFFER(l_tm_buffer_write_int32le, WRITE_32((int32_t) value, a[3], a[2], a[1], a[0])); WRITE_BUFFER(l_tm_buffer_write_int32be, WRITE_32((int32_t) value, a[0], a[1], a[2], a[3])); static int l_tm_buffer_read_float (lua_State *L) { uint8_t *ud = (uint8_t *) lua_touserdata(L, 1); size_t index = (size_t) lua_tonumber(L, 2); uint8_t le = (int) lua_tonumber(L, 3);