int zlib_test(int argc, char **argv) { int zlib_test(int argc, char **argv) int ret; /* avoid end-of-line conversions */ SET_BINARY_MODE(stdin); SET_BINARY_MODE(stdout); /* do compression if no arguments */ if (argc == 1) { ret = zlib_compress(stdin, stdout, Z_DEFAULT_COMPRESSION); if (ret != Z_OK) zerr(ret); return ret; } /* do decompression if -d specified */ else if (argc == 2 && strcmp(argv[1], "-d") == 0) { ret = zlib_decompress(stdin, stdout); if (ret != Z_OK) zerr(ret); return ret; } /* otherwise, report usage */ else { fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr); return 1; } }
int32 send_parse(int8 *buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data) { // Модификация заголовка исходящего пакета // Суть преобразований: // - отправить клиенту номер последнего полученного от него пакета // - присвоить исходящему пакету номер последнего отправленного клиенту пакета +1 // - записать текущее время отправки пакета WBUFW(buff,0) = map_session_data->server_packet_id; WBUFW(buff,2) = map_session_data->client_packet_id; // сохранение текущего времени (32 BIT!) WBUFL(buff,8) = (uint32)time(NULL); //Сжимаем данные без учета заголовка //Возвращаемый размер в 8 раз больше реальных данных uint32 PacketSize = zlib_compress(buff+FFXI_HEADER_SIZE, *buffsize-FFXI_HEADER_SIZE, PTempBuff, *buffsize, zlib_compress_table); //Запись размера данных без учета заголовка WBUFL(PTempBuff,(PacketSize+7)/8) = PacketSize; //Расчет hash'a также без учета заголовка, но с учетом записанного выше размера данных PacketSize = (PacketSize+7)/8+4; uint8 hash[16]; md5((uint8*)PTempBuff, hash, PacketSize); memcpy(PTempBuff+PacketSize, hash, 16); PacketSize += 16; if (PacketSize > map_config.buffer_size + 20) { ShowFatalError(CL_RED"%Memory manager: PTempBuff is overflowed (%u)\n" CL_RESET, PacketSize); } //making total packet memcpy(buff+FFXI_HEADER_SIZE, PTempBuff, PacketSize); uint32 CypherSize = (PacketSize/4)&-2; blowfish_t* pbfkey = &map_session_data->blowfish; for(uint32 j = 0; j < CypherSize; j += 2) { blowfish_encipher((uint32*)(buff)+j+7, (uint32*)(buff)+j+8, pbfkey->P, pbfkey->S[0]); } // контролируем размер отправляемого пакета. в случае, // если его размер превышает 1400 байт (размер данных + 42 байта IP заголовок), // то клиент игнорирует пакет и возвращает сообщение о его потере // в случае возникновения подобной ситуации выводим предупреждующее сообщение и // уменьшаем размер BuffMaxSize с шагом в 4 байта до ее устранения (вручную) *buffsize = PacketSize+FFXI_HEADER_SIZE; if (*buffsize > 1350) { ShowWarning(CL_YELLOW"send_parse: packet is very big <%u>\n" CL_RESET,*buffsize); } return 0; }
static int compress_inner(grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output) { switch (algorithm) { case GRPC_COMPRESS_NONE: /* the fallback path always needs to be send uncompressed: we simply rely on that here */ return 0; case GRPC_COMPRESS_DEFLATE: return zlib_compress(input, output, 0); case GRPC_COMPRESS_GZIP: return zlib_compress(input, output, 1); case GRPC_COMPRESS_ALGORITHMS_COUNT: break; } gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm); return 0; }
// 对数据包进行加密和压缩 char *pkg_compress_encrypt(const packet_parser_t *pkg, const char *source, int source_len, int *cipher_body_len) { char *encrypt_string; char *compress_string = NULL; uLongf compress_dest_len; if (source_len < 0) { source_len = strlen(source); } // 先对数据源进行压缩 if (pkg->compress_hook == NULL) { zlib_compress((unsigned char **)(&compress_string), &compress_dest_len, (unsigned char *)source, source_len, 0, COMPRESS_TYPE); } else { pkg->compress_hook((unsigned char **)(&compress_string), &compress_dest_len, (unsigned char *)source, source_len, 0, COMPRESS_TYPE); } printf("source len:%d\tcompress len:%ld\n", source_len, compress_dest_len); // 再对数据进行加密 if (strcmp(pkg->curr_ert.transfer_ert_type, ENCRYPT_AES_128) == 0) { if (pkg->sym_encrypt_hook == NULL) { encrypt_string = (char *)aes_encrypt((unsigned char *)compress_string, compress_dest_len, cipher_body_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_ENCRYPT); } else { encrypt_string = (char *)aes_encrypt((unsigned char *)compress_string, compress_dest_len, cipher_body_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_ENCRYPT); } } else if (strcmp(pkg->curr_ert.transfer_ert_type, ENCRYPT_DES3_128) == 0) { if (pkg->sym_encrypt_hook == NULL) { encrypt_string = (char *)des3_encrypt((unsigned char *)compress_string, compress_dest_len, cipher_body_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_ENCRYPT); } else { encrypt_string = (char *)pkg->sym_encrypt_hook((unsigned char *)compress_string, compress_dest_len, cipher_body_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_ENCRYPT); } } if (compress_string) { free(compress_string); } return encrypt_string; }
static void _bta_write_cell(FILE *fp, bta_cell_t *btac) { fp_write16le(fp, btac->x); fp_write16le(fp, btac->y); fp_write16le(fp, btac->width); fp_write16le(fp, btac->height); fp_write16le(fp, btac->delay); btac->gfx = zlib_compress(btac->gfx); /* Write the compressed size */ fp_write32le(fp, btac->gfx->size); xfwrite(btac->gfx->buf, sizeof(uint8_t), btac->gfx->size, fp); }
char *pkg_uncompress_decrypt(const packet_parser_t *pkg, const char *source, int source_len, int plain_body_len) { char *encrypt_string; char *compress_string = NULL; int decrypt_dest_len; uLongf uncompress_dest_len; // 先对数据源进行解密 if (strcmp(pkg->curr_ert.transfer_ert_type, ENCRYPT_AES_128) == 0) { if (pkg->sym_encrypt_hook == NULL) { encrypt_string = (char *)aes_encrypt((unsigned char *)source, source_len, &decrypt_dest_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_DECRYPT); } else { encrypt_string = (char *)pkg->sym_encrypt_hook((unsigned char *)source, source_len, &decrypt_dest_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_DECRYPT); } } else if (strcmp(pkg->curr_ert.transfer_ert_type, ENCRYPT_DES3_128) == 0) { if (pkg->sym_encrypt_hook == NULL) { encrypt_string = (char *)des3_encrypt((unsigned char *)source, source_len, &decrypt_dest_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_DECRYPT); } else { encrypt_string = (char *)pkg->sym_encrypt_hook((unsigned char *)source, source_len, &decrypt_dest_len, (char *)pkg->curr_ert.ert_keys[2], CRYPT_TYPE_DECRYPT); } } // 再对数据进行解压缩 if (pkg->compress_hook == NULL) { zlib_compress((unsigned char **)(&compress_string), &uncompress_dest_len, (unsigned char *)encrypt_string, decrypt_dest_len, plain_body_len, UNCOMPRESS_TYPE); } else { pkg->compress_hook((unsigned char **)(&compress_string), &uncompress_dest_len, (unsigned char *)encrypt_string, decrypt_dest_len, plain_body_len, UNCOMPRESS_TYPE); } if (encrypt_string) { free(encrypt_string); } return compress_string; }
int main(int argc, char **argv) { FILE **infiles; FILE *outfile; if (argc == 1 || argc == 2) { usage(); return(EXIT_FAILURE); } if (!strcmp(argv[1], "-d")) { // Decompress infiles = calloc(1, sizeof(FILE*)); if (argc != 4) { usage(); return(EXIT_FAILURE); } infiles[0] = fopen(argv[2], "rb"); if (infiles[0] == NULL) { fprintf(stderr, "Error. Cannot open input file %s", argv[2]); return(EXIT_FAILURE); } outfile = fopen(argv[3], "wb"); if (outfile == NULL) { fprintf(stderr, "Error. Cannot open output file %s", argv[3]); return(EXIT_FAILURE); } return zlib_decompress(infiles[0], outfile); } else { // Compress infiles = calloc(argc-2, sizeof(FILE*)); for (uint16_t i = 0; i < argc-2; i++) { infiles[i] = fopen(argv[i+1], "rb"); if (infiles[i] == NULL) { fprintf(stderr, "Error. Cannot open input file %s", argv[i+1]); return(EXIT_FAILURE); } } outfile = fopen(argv[argc-1], "wb"); if (outfile == NULL) { fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]); return(EXIT_FAILURE); } return zlib_compress(infiles, argc-2, outfile); } }
CGOGN_IO_API void write_binary_xml_data(std::ostream& output, const char* data_str, std::size_t size, bool compress) { std::vector<char> data; std::vector<uint32> header; if (!compress) { header.push_back(static_cast<uint32>(size)); data.resize(sizeof(uint32) + size); std::memcpy(&data[0], reinterpret_cast<const char*>(&header[0]), sizeof(uint32)* header.size()); std::memcpy(&data[sizeof(uint32)], data_str, size); } else { const std::size_t uncompressed_chunk_size = std::min(size, std::size_t(1048576)); const std::vector<std::vector<unsigned char>>& compressed_blocks = zlib_compress(reinterpret_cast<const unsigned char*>(data_str), size, uncompressed_chunk_size); std::size_t compressed_size{0ul}; const std::size_t last_block_size = (compressed_blocks.size() == 1ul) ? uncompressed_chunk_size : size % uncompressed_chunk_size; header.push_back(static_cast<uint32>(compressed_blocks.size())); header.push_back(static_cast<uint32>(uncompressed_chunk_size)); header.push_back(static_cast<uint32>(last_block_size)); for (const auto& block : compressed_blocks) { header.push_back(static_cast<uint32>(block.size())); compressed_size += block.size(); } const auto& encoded_header = base64_encode(reinterpret_cast<char*>(&header[0]), header.size() * sizeof(uint32)); output.write(&encoded_header[0], encoded_header.size()); data.resize(compressed_size); char* data_ptr = &data[0]; for (const auto& block : compressed_blocks) { const char* src = reinterpret_cast<const char*>(&block[0]); std::memcpy(data_ptr, src, block.size()); data_ptr += block.size(); } } const auto& encoded_data = base64_encode(&data[0], data.size()); output.write(&encoded_data[0], encoded_data.size()); }
/* jffs2_compress: * @data: Pointer to uncompressed data * @cdata: Pointer to buffer for compressed data * @datalen: On entry, holds the amount of data available for compression. * On exit, expected to hold the amount of data actually compressed. * @cdatalen: On entry, holds the amount of space available for compressed * data. On exit, expected to hold the actual size of the compressed * data. * * Returns: Byte to be stored with data indicating compression type used. * Zero is used to show that the data could not be compressed - the * compressed version was actually larger than the original. * * If the cdata buffer isn't large enough to hold all the uncompressed data, * jffs2_compress should compress as much as will fit, and should set * *datalen accordingly to show the amount of data which were compressed. */ unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 *datalen, __u32 *cdatalen) { int ret; ret = zlib_compress(data_in, cpage_out, datalen, cdatalen); if (!ret) { return JFFS2_COMPR_ZLIB; } #if 0 /* Disabled 23/9/1. With zlib it hardly ever gets a look in */ ret = dynrubin_compress(data_in, cpage_out, datalen, cdatalen); if (!ret) { return JFFS2_COMPR_DYNRUBIN; } #endif #if 0 /* Disabled 26/2/1. Obsoleted by dynrubin */ ret = rubinmips_compress(data_in, cpage_out, datalen, cdatalen); if (!ret) { return JFFS2_COMPR_RUBINMIPS; } #endif /* rtime does manage to recompress already-compressed data */ ret = rtime_compress(data_in, cpage_out, datalen, cdatalen); if (!ret) { return JFFS2_COMPR_RTIME; } #if 0 /* We don't need to copy. Let the caller special-case the COMPR_NONE case. */ /* If we get here, no compression is going to work */ /* But we might want to use the fragmentation part -- Arjan */ memcpy(cpage_out,data_in,min(*datalen,*cdatalen)); if (*datalen > *cdatalen) *datalen = *cdatalen; #endif return JFFS2_COMPR_NONE; /* We failed to compress */ }
static void on_msg_recv_cb(wslay_event_context_ptr ev, const struct wslay_event_on_msg_recv_arg *arg, void *user_data) { struct transaction_t *txn = (struct transaction_t *) user_data; struct ws_context *ctx = (struct ws_context *) txn->ws_ctx; struct buf inbuf = BUF_INITIALIZER, outbuf = BUF_INITIALIZER; struct wslay_event_msg msgarg = { arg->opcode, NULL, 0 }; uint8_t rsv = WSLAY_RSV_NONE; double cmdtime, nettime; const char *err_msg; int r, err_code = 0; /* Place client request into a buf */ buf_init_ro(&inbuf, (const char *) arg->msg, arg->msg_length); /* Decompress request, if necessary */ if (wslay_get_rsv1(arg->rsv)) { /* Add trailing 4 bytes */ buf_appendmap(&inbuf, "\x00\x00\xff\xff", 4); r = zlib_decompress(txn, buf_base(&inbuf), buf_len(&inbuf)); if (r) { syslog(LOG_ERR, "on_msg_recv_cb(): zlib_decompress() failed"); err_code = WSLAY_CODE_PROTOCOL_ERROR; err_msg = DECOMP_FAILED_ERR; goto err; } buf_move(&inbuf, &txn->zbuf); } /* Log the uncompressed client request */ buf_truncate(&ctx->log, ctx->log_tail); buf_appendcstr(&ctx->log, " ("); if (txn->strm_ctx) { buf_printf(&ctx->log, "stream-id=%d; ", http2_get_streamid(txn->strm_ctx)); } buf_printf(&ctx->log, "opcode=%s; rsv=0x%x; length=%ld", wslay_str_opcode(arg->opcode), arg->rsv, arg->msg_length); switch (arg->opcode) { case WSLAY_CONNECTION_CLOSE: buf_printf(&ctx->log, "; status=%d; msg='%s'", arg->status_code, buf_len(&inbuf) ? buf_cstring(&inbuf)+2 : ""); txn->flags.conn = CONN_CLOSE; break; case WSLAY_TEXT_FRAME: case WSLAY_BINARY_FRAME: if (txn->conn->logfd != -1) { /* Telemetry logging */ struct iovec iov[2]; int niov = 0; assert(!buf_len(&txn->buf)); buf_printf(&txn->buf, "<%ld<", time(NULL)); /* timestamp */ WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&txn->buf), buf_len(&txn->buf)); WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&inbuf), buf_len(&inbuf)); writev(txn->conn->logfd, iov, niov); buf_reset(&txn->buf); } /* Process the request */ r = ctx->data_cb(&inbuf, &outbuf, &ctx->log, &ctx->cb_rock); if (r) { err_code = (r == HTTP_SERVER_ERROR ? WSLAY_CODE_INTERNAL_SERVER_ERROR : WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA); err_msg = error_message(r); goto err; } if (txn->conn->logfd != -1) { /* Telemetry logging */ struct iovec iov[2]; int niov = 0; assert(!buf_len(&txn->buf)); buf_printf(&txn->buf, ">%ld>", time(NULL)); /* timestamp */ WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&txn->buf), buf_len(&txn->buf)); WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&outbuf), buf_len(&outbuf)); writev(txn->conn->logfd, iov, niov); buf_reset(&txn->buf); } /* Compress the server response, if supported by the client */ if (ctx->ext & EXT_PMCE_DEFLATE) { r = zlib_compress(txn, ctx->pmce.deflate.no_context ? COMPRESS_START : 0, buf_base(&outbuf), buf_len(&outbuf)); if (r) { syslog(LOG_ERR, "on_msg_recv_cb(): zlib_compress() failed"); err_code = WSLAY_CODE_INTERNAL_SERVER_ERROR; err_msg = COMP_FAILED_ERR; goto err; } /* Trim the trailing 4 bytes */ buf_truncate(&txn->zbuf, buf_len(&txn->zbuf) - 4); buf_move(&outbuf, &txn->zbuf); rsv |= WSLAY_RSV1_BIT; } /* Queue the server response */ msgarg.msg = (const uint8_t *) buf_base(&outbuf); msgarg.msg_length = buf_len(&outbuf); wslay_event_queue_msg_ex(ev, &msgarg, rsv); /* Log the server response */ buf_printf(&ctx->log, ") => \"Success\" (opcode=%s; rsv=0x%x; length=%ld", wslay_str_opcode(msgarg.opcode), rsv, msgarg.msg_length); break; } err: if (err_code) { size_t err_msg_len = strlen(err_msg); syslog(LOG_DEBUG, "wslay_event_queue_close()"); wslay_event_queue_close(ev, err_code, (uint8_t *) err_msg, err_msg_len); /* Log the server response */ buf_printf(&ctx->log, ") => \"Fail\" (opcode=%s; rsv=0x%x; length=%ld" "; status=%d; msg='%s'", wslay_str_opcode(WSLAY_CONNECTION_CLOSE), rsv, err_msg_len, err_code, err_msg); } /* Add timing stats */ cmdtime_endtimer(&cmdtime, &nettime); buf_printf(&ctx->log, ") [timing: cmd=%f net=%f total=%f]", cmdtime, nettime, cmdtime + nettime); syslog(LOG_INFO, "%s", buf_cstring(&ctx->log)); buf_free(&inbuf); buf_free(&outbuf); }
int main(int argc, char **argv) { FILE **infiles; char **infile_names; FILE *outfile; if (argc == 1 || argc == 2) { usage(); return(EXIT_FAILURE); } if (!strcmp(argv[1], "-d")) { // Decompress infiles = calloc(1, sizeof(FILE*)); if (argc != 4) { usage(); return(EXIT_FAILURE); } infiles[0] = fopen(argv[2], "rb"); if (infiles[0] == NULL) { fprintf(stderr, "Error. Cannot open input file %s\n\n", argv[2]); return(EXIT_FAILURE); } outfile = fopen(argv[3], "wb"); if (outfile == NULL) { fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[3]); return(EXIT_FAILURE); } return zlib_decompress(infiles[0], outfile); } else { // Compress or gemerate version info bool hardnested_mode = false; bool generate_version_file = false; int num_input_files = 0; if (!strcmp(argv[1], "-t")) { // compress one hardnested table if (argc != 4) { usage(); return(EXIT_FAILURE); } hardnested_mode = true; num_input_files = 1; } else if (!strcmp(argv[1], "-v")) { // generate version info generate_version_file = true; num_input_files = argc-3; } else { // compress 1..n fpga files num_input_files = argc-2; } infiles = calloc(num_input_files, sizeof(FILE*)); infile_names = calloc(num_input_files, sizeof(char*)); for (uint16_t i = 0; i < num_input_files; i++) { infile_names[i] = argv[i+((hardnested_mode || generate_version_file)?2:1)]; infiles[i] = fopen(infile_names[i], "rb"); if (infiles[i] == NULL) { fprintf(stderr, "Error. Cannot open input file %s\n\n", infile_names[i]); return(EXIT_FAILURE); } } outfile = fopen(argv[argc-1], "wb"); if (outfile == NULL) { fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[argc-1]); return(EXIT_FAILURE); } if (generate_version_file) { if (generate_fpga_version_info(infiles, infile_names, num_input_files, outfile)) { return(EXIT_FAILURE); } } else { return zlib_compress(infiles, num_input_files, outfile, hardnested_mode); } } }
int32 send_parse(int8 *buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data) { // Модификация заголовка исходящего пакета // Суть преобразований: // - отправить клиенту номер последнего полученного от него пакета // - присвоить исходящему пакету номер последнего отправленного клиенту пакета +1 // - записать текущее время отправки пакета WBUFW(buff, 0) = map_session_data->server_packet_id; WBUFW(buff, 2) = map_session_data->client_packet_id; // сохранение текущего времени (32 BIT!) WBUFL(buff, 8) = (uint32)time(nullptr); // собираем большой пакет, состоящий из нескольких маленьких CCharEntity *PChar = map_session_data->PChar; CBasicPacket* PSmallPacket; uint32 PacketSize = UINT32_MAX; uint32 PacketCount = PChar->getPacketCount(); uint8 packets = 0; while (PacketSize > 1300 - FFXI_HEADER_SIZE - 16) //max size for client to accept { *buffsize = FFXI_HEADER_SIZE; PacketList_t packetList = PChar->getPacketList(); packets = 0; while (!packetList.empty() && *buffsize + packetList.front()->length() < map_config.buffer_size && packets < PacketCount) { PSmallPacket = packetList.front(); PSmallPacket->sequence(map_session_data->server_packet_id); memcpy(buff + *buffsize, *PSmallPacket, PSmallPacket->length()); *buffsize += PSmallPacket->length(); packetList.pop_front(); packets++; } //Сжимаем данные без учета заголовка //Возвращаемый размер в 8 раз больше реальных данных PacketSize = zlib_compress(buff + FFXI_HEADER_SIZE, *buffsize - FFXI_HEADER_SIZE, PTempBuff, *buffsize, zlib_compress_table); WBUFL(PTempBuff, (PacketSize + 7) / 8) = PacketSize; PacketSize = (PacketSize + 7) / 8 + 4; PacketCount /= 2; } PChar->erasePackets(packets); //Запись размера данных без учета заголовка uint8 hash[16]; md5((uint8*)PTempBuff, hash, PacketSize); memcpy(PTempBuff + PacketSize, hash, 16); PacketSize += 16; if (PacketSize > map_config.buffer_size + 20) { ShowFatalError(CL_RED"%Memory manager: PTempBuff is overflowed (%u)\n" CL_RESET, PacketSize); } //making total packet memcpy(buff + FFXI_HEADER_SIZE, PTempBuff, PacketSize); uint32 CypherSize = (PacketSize / 4)&-2; blowfish_t* pbfkey = &map_session_data->blowfish; for (uint32 j = 0; j < CypherSize; j += 2) { blowfish_encipher((uint32*)(buff)+j + 7, (uint32*)(buff)+j + 8, pbfkey->P, pbfkey->S[0]); } // контролируем размер отправляемого пакета. в случае, // если его размер превышает 1400 байт (размер данных + 42 байта IP заголовок), // то клиент игнорирует пакет и возвращает сообщение о его потере // в случае возникновения подобной ситуации выводим предупреждующее сообщение и // уменьшаем размер BuffMaxSize с шагом в 4 байта до ее устранения (вручную) *buffsize = PacketSize + FFXI_HEADER_SIZE; return 0; }
// returns the length of the packed data // TBH, I really can't be stuffed writing a buffered copy/compress/decompressor // // (and anyway, it may not work with future compression routines, so meh) uint32_t rco_write_resource (FILE * dest, rRCOEntry * entry, uint32_t destCompression, writerco_options * opts, rRCOFile * rco) { uint32_t len = 0; uint8_t *bufferMid = (uint8_t *) read_resource (entry, &len); if (!bufferMid) { if (entry->labelOffset) warning ("Failed to read resource '%s'.", rco->labels + entry->labelOffset); return 0; } if (len != entry->srcLenUnpacked) { free (bufferMid); return 0; } uint8_t *bufferOut; uint32_t packedSize = 0; if (destCompression == RCO_DATA_COMPRESSION_ZLIB) { uint32_t compSize = compressBound (entry->srcLenUnpacked); bufferOut = (uint8_t *) malloc (compSize); packedSize = zlib_compress (bufferMid, entry->srcLenUnpacked, bufferOut, compSize, opts->zlibLevel, opts->zlibMethod); if (!packedSize) { if (entry->labelOffset) warning ("Failed to compress resource '%s'.", rco->labels + entry->labelOffset); return 0; } free (bufferMid); } else if (destCompression == RCO_DATA_COMPRESSION_RLZ) { #ifdef DISABLE_RLZ error ("RLZ compression not supported."); exit (1); #endif bufferOut = (uint8_t *) malloc (entry->srcLenUnpacked); packedSize = rlz_compress (bufferMid, entry->srcLenUnpacked, bufferOut, entry->srcLenUnpacked, opts->rlzMode); if (!packedSize) { if (entry->labelOffset) warning ("Failed to compress resource '%s'.", rco->labels + entry->labelOffset); return 0; } free (bufferMid); } else { bufferOut = bufferMid; packedSize = entry->srcLenUnpacked; } filewrite (dest, bufferOut, packedSize); free (bufferOut); /* * char buffer[65536], outBuffer[65536]; uint32_t len=entry->srcLen; z_stream * out; if(destStream == RCO_DATA_COMPRESSION_ZLIB) { ZLIB_INIT_DEFLATE(out, * 9, Z_DEFAULT_STRATEGY); out.next_in = buffer; out.avail_in = 65536; * out.next_out = outBuffer; out.avail_out = 65536; } * * // copy with buffer while(len) { uint32_t readAmt = (len < 65536 ? len : * 65536); if(!fileread(src, &buffer, readAmt)) { fclose(src); return FALSE; * } * * if(destCompression == RCO_DATA_COMPRESSION_NONE) filewrite(dest, &buffer, * readAmt); else if(destCompression == RCO_DATA_COMPRESSION_ZLIB) { * * } * * len -= readAmt; } * * // TOxDO: also don't forget to check lenUnpacked * * fclose(src); * * if(destStream == RCO_DATA_COMPRESSION_ZLIB) deflateEnd(&out); */ // 4byte alignment if (packedSize % 4) { uint32_t zero = 0; filewrite (dest, &zero, 4 - (packedSize % 4)); } return packedSize; }
lzo_bool x_compress(file_t *fip, file_t *fop, header_t *h) { lzo_bool ok = 0; init_compress_header(h,fip,fop); switch (h->method) { #if defined(WITH_LZO) case M_LZO1X_1: case M_LZO1X_1_15: case M_LZO1X_999: lzo_init_compress_header(h); break; #endif #if defined(WITH_NRV) case M_NRV1A: case M_NRV1B: case M_NRV2A: case M_NRV2B: nrv_init_compress_header(h); break; #endif #if defined(WITH_ZLIB) case M_ZLIB: zlib_init_compress_header(h); break; #endif default: fatal(fip,"Internal error"); break; } if (!x_enter(h)) e_memory(); if (opt_verbose > 1) { if (opt_unlink) fprintf(con_term,"replacing %s with %s", fip->name, fop->name); else fprintf(con_term,"compressing %s into %s", fip->name, fop->name); fflush(con_term); set_err_nl(1); } write_header(fop,h); fip->bytes_processed = fop->bytes_processed = 0; switch (h->method) { #if defined(WITH_LZO) case M_LZO1X_1: case M_LZO1X_1_15: case M_LZO1X_999: ok = lzo_compress(fip,fop,h); break; #endif #if defined(WITH_NRV) case M_NRV1A: case M_NRV1B: case M_NRV2A: case M_NRV2B: ok = nrv_compress(fip,fop,h); break; #endif #if defined(WITH_ZLIB) case M_ZLIB: ok = zlib_compress(fip,fop,h); break; #endif default: fatal(fip,"Internal error"); ok = 0; break; } if (opt_cmd == CMD_COMPRESS && opt_verbose > 1) { fprintf(con_term, ok ? "\n" : " FAILED\n"); fflush(con_term); } set_err_nl(0); x_leave(h); return ok; }
// packing: use RCO_DATA_COMPRESSION_* constants uint8_t write_rco (rRCOFile * rco, char *fn, writerco_options opts) { uint32_t i; rRCOFile_writehelper rcoH; // delete file if exists if (file_exists (fn)) { if (remove (fn)) { error ("Unable to write to file %s", fn); return FALSE; } } rcoH.rco = rco; rcoH.fp = fopen (fn, "wb"); if (!rcoH.fp) { error ("Unable to open file %s", fn); return FALSE; } PRFHeader header; header.signature = RCO_SIGNATURE; header.version = (opts.packHeader == RCO_DATA_COMPRESSION_RLZ ? 0x95 : opts.packHeader == RCO_DATA_COMPRESSION_ZLIB ? 0x90 : 0x71); if (rco->verId) { // we won't actually use specified value, // rather, we'll require using the minimum // version from above if (rco->verId > header.version) header.version = rco->verId; } header.null = 0; header.compression = (opts.packHeader << 4) | (rco->umdFlag & 0xF); header.pMainTable = 0xA4; // pretty much always the case // set other sections to nothing for now header.pVSMXTable = header.pTextTable = header.pSoundTable = header.pModelTable = header.pImgTable = header.pObjTable = header.pAnimTable = RCO_NULL_PTR; header.pUnknown = header.pFontTable = RCO_NULL_PTR; // don't know positions of text/label/event data too, but we do know the // lengths for label/events // header.pTextData = header.pLabelData = header.pEventData = 0; header.lLabelData = rco->labelsLen; header.lEventData = rco->eventsLen; header.lTextData = 0; // set pointer sections to blank too header.pTextPtrs = header.pImgPtrs = header.pModelPtrs = header.pSoundPtrs = header.pObjPtrs = header.pAnimPtrs = RCO_NULL_PTR; header.lTextPtrs = header.lImgPtrs = header.lModelPtrs = header.lSoundPtrs = header.lObjPtrs = header.lAnimPtrs = 0; // also blank... header.pImgData = header.pSoundData = header.pModelData = RCO_NULL_PTR; header.lImgData = header.lSoundData = header.lModelData = 0; header.unknown[0] = header.unknown[1] = header.unknown[2] = 0xFFFFFFFF; // write resources to a separate file to get around the issue of unknown // packed size when writing the header (and you can't change it backed after // the header is packed...) FILE *fTmp = NULL; if ((rco->tblImage && rco->tblImage->numSubentries) || (rco->tblSound && rco->tblSound->numSubentries) || (rco->tblModel && rco->tblModel->numSubentries)) { uint32_t totalPackedLen = 0; rRCOEntry *rcoNode; fTmp = tmpfile (); if (rco->tblImage && rco->tblImage->numSubentries) { for (rcoNode = rco->tblImage->firstChild; rcoNode; rcoNode = rcoNode->next) { // our compression decision thing uint32_t c = ((rRCOImgModelEntry *) (rcoNode->extra))->compression; if (((rRCOImgModelEntry *) (rcoNode->extra))->format < RCO_IMG_BMP) { if (opts.packImgCompr != -1) c = opts.packImgCompr; } else { if (opts.packImg != -1) c = opts.packImg; } if (rcoNode->srcLenUnpacked) { rcoNode->srcLen = rco_write_resource (fTmp, rcoNode, c, &opts, rco); if (!rcoNode->srcLen && rcoNode->labelOffset != RCO_NULL_PTR) warning ("[resource] Can't write image resource '%s'!", rco->labels + rcoNode->labelOffset); } rcoNode->srcCompression = c; rcoNode->srcAddr = totalPackedLen; totalPackedLen += (rcoNode->srcLen % 4 ? (rcoNode->srcLen / 4) * 4 + 4 : rcoNode->srcLen); } header.lImgData = totalPackedLen; } totalPackedLen = 0; if (rco->tblSound && rco->tblSound->numSubentries) { for (rcoNode = rco->tblSound->firstChild; rcoNode; rcoNode = rcoNode->next) { if (rcoNode->srcLenUnpacked) { uint32_t packedLen = rco_write_resource (fTmp, rcoNode, RCO_DATA_COMPRESSION_NONE, &opts, rco); if (!packedLen && rcoNode->labelOffset != RCO_NULL_PTR) warning ("[resource] Can't write sound resource '%s'!", rco->labels + rcoNode->labelOffset); totalPackedLen += ALIGN_TO_4 (packedLen); // if(totalPackedLen %4) totalPackedLen += 4-(totalPackedLen%4); } } header.lSoundData = totalPackedLen; } totalPackedLen = 0; if (rco->tblModel && rco->tblModel->numSubentries) { for (rcoNode = rco->tblModel->firstChild; rcoNode; rcoNode = rcoNode->next) { uint32_t c = ((rRCOImgModelEntry *) (rcoNode->extra))->compression; if (opts.packModel != -1) c = opts.packModel; if (rcoNode->srcLenUnpacked) { rcoNode->srcLen = rco_write_resource (fTmp, rcoNode, c, &opts, rco); if (!rcoNode->srcLen && rcoNode->labelOffset != RCO_NULL_PTR) warning ("[resource] Can't write model resource '%s'!", rco->labels + rcoNode->labelOffset); } rcoNode->srcCompression = c; rcoNode->srcAddr = totalPackedLen; totalPackedLen += (rcoNode->srcLen % 4 ? (rcoNode->srcLen / 4) * 4 + 4 : rcoNode->srcLen); } header.lModelData = totalPackedLen; } rewind (fTmp); } filewrite (rcoH.fp, &header, sizeof (header)); rcoH.tables = 0; // if compressing, write to memory if (opts.packHeader) { rcoH.tables = malloc (RCO_WRITE_MEM_BUFFER); rcoH.memPos = rcoH.tablesSize = 0; rcoH.tablesBuffered = RCO_WRITE_MEM_BUFFER; rcoH.memOffset = ftell (rcoH.fp); } rcoH.sizeImg = rcoH.sizeModel = rcoH.sizeSound = rcoH.sizeText = 0; rcoH.longestLangData = 0; write_entry (&rcoH, &(rco->tblMain), 0xA4 /* typically where the main * table is written to */ , 0, TRUE); // fix up object/anim extra data { if (rco->tblObj) rco_write_fix_refs (rco->tblObj, &rcoH, rco, RCO_OBJ_EXTRA_LEN, RCO_OBJ_EXTRA_LEN_NUM, TRUE); if (rco->tblAnim) rco_write_fix_refs (rco->tblAnim, &rcoH, rco, RCO_ANIM_EXTRA_LEN, RCO_ANIM_EXTRA_LEN_NUM, FALSE); } { // write hashtable data /* { // special case for text hashes if(rco->numPtrText) { header.pTextPtrs * = rcowrite_ftell(&rcoH); for(i=0; i<rco->numPtrText; i++) { uint32_t * writePtr = 0; if(rco->ptrText[i].textEntry && rco->ptrText[i].index) * writePtr = rco->ptrText[i].textEntry->offset + sizeof(RCOEntry) + * sizeof(RCOTextEntry) + (rco->ptrText[i].index - * ((rRCOTextEntry*)(rco->ptrText[i].textEntry->extra))->indexes)*sizeof(RCOTextIndex); * rco_fwrite(&rcoH, &writePtr, sizeof(uint32_t)); } } } */ if (rco->tblText) { header.pTextPtrs = rcowrite_ftell (&rcoH); header.lTextPtrs = 0; // generate sorted list of text entries, sorted by languageID rRCOEntry **sList = make_sorted_list_of_subentries (rco->tblText, text_hash_table_qsort); for (i = 0; i < rco->tblText->numSubentries; i++) header.lTextPtrs += write_text_hash_table (&rcoH, sList[i], rco); free (sList); header.lTextPtrs *= sizeof (uint32_t); } if (rco->tblImage) { header.pImgPtrs = rcowrite_ftell (&rcoH); header.lImgPtrs = write_hash_table (&rcoH, rco->tblImage, rco) * sizeof (uint32_t); } if (rco->tblModel) { header.pModelPtrs = rcowrite_ftell (&rcoH); header.lModelPtrs = write_hash_table (&rcoH, rco->tblModel, rco) * sizeof (uint32_t); } if (rco->tblSound) { header.pSoundPtrs = rcowrite_ftell (&rcoH); header.lSoundPtrs = write_hash_table (&rcoH, rco->tblSound, rco) * sizeof (uint32_t); } if (rco->tblObj) { header.pObjPtrs = rcowrite_ftell (&rcoH); header.lObjPtrs = write_hash_table (&rcoH, rco->tblObj, rco) * sizeof (uint32_t); } if (rco->tblAnim) { header.pAnimPtrs = rcowrite_ftell (&rcoH); header.lAnimPtrs = write_hash_table (&rcoH, rco->tblAnim, rco) * sizeof (uint32_t); } /* * #define RCO_WRITERCO_WRITE_PTR_SECT(pd, pl, hp) { \ if(pl) { \ hp = * rcowrite_ftell(&rcoH); \ for(i=0; i<pl; i++) { \ if(pd[i]) \ * rco_fwrite(&rcoH, &(((rRCOEntry*)(pd[i]))->offset), sizeof(uint32_t)); \ * else { \ uint32_t zero = 0; \ rco_fwrite(&rcoH, &zero, sizeof(uint32_t)); \ * } \ } \ } \ } //RCO_WRITERCO_WRITE_PTR_SECT(rco->ptrText, * rco->numPtrText, header.pTextPtrs); * RCO_WRITERCO_WRITE_PTR_SECT(rco->ptrImg, rco->numPtrImg, * header.pImgPtrs); RCO_WRITERCO_WRITE_PTR_SECT(rco->ptrModel, * rco->numPtrModel, header.pModelPtrs); * RCO_WRITERCO_WRITE_PTR_SECT(rco->ptrSound, rco->numPtrSound, * header.pSoundPtrs); RCO_WRITERCO_WRITE_PTR_SECT(rco->ptrObj, * rco->numPtrObj, header.pObjPtrs); * RCO_WRITERCO_WRITE_PTR_SECT(rco->ptrAnim, rco->numPtrAnim, * header.pAnimPtrs); */ } { // write label/event data (and text if // applicable) // write text (note, old behaviour - newer RCOs have text written in a // different location) if (!opts.packText && rco->tblText && rco->tblText->numSubentries) { rRCOEntry *rcoNode; header.pTextData = rcowrite_ftell (&rcoH); header.lTextData = rcoH.sizeText; for (rcoNode = rco->tblText->firstChild; rcoNode; rcoNode = rcoNode->next) { rco_write_text_resource (&rcoH, rcoNode, RCO_DATA_COMPRESSION_NONE, &opts, ((rRCOTextEntry *) (rcoNode->extra))->lang, (rco->tblText->lastChild == rcoNode)); } } // write label+event data header.pLabelData = rcowrite_ftell (&rcoH); if (rco->labelsLen) rco_fwrite (&rcoH, rco->labels, rco->labelsLen); header.pEventData = rcowrite_ftell (&rcoH); if (rco->eventsLen) rco_fwrite (&rcoH, rco->events, rco->eventsLen); else if (rco->tblObj || rco->tblAnim) { // weird case: if there's // object entries, there will // be 4 bytes for events; I'll // assume this covers anim as // well (although there isn't // an RCO with anim that // doesn't have objects) uint32_t zero = 0; rco_fwrite (&rcoH, &zero, sizeof (zero)); header.lEventData = sizeof (zero); } // the text pointer is weird in that if there's no text, it's set equal to // the label pointer; even weirder, some RCOs have a null pointer (for // FW5.00 all except lftv_* RCOs have null pointers for pTextData if // there's no text) // my theory: if compressing, it will be RCO_NULL_PTR, otherwise it'll = // header.pLabelData // if(!header.lTextData) header.pTextData = RCO_NULL_PTR; // if(!header.lTextData) header.pTextData = header.pLabelData; if (!header.lTextData) header.pTextData = (opts.packHeader ? RCO_NULL_PTR : header.pLabelData); } // flush compression stuff here HeaderComprInfo ci; if (opts.packHeader) { uint8_t *bufferOut = NULL; ci.lenLongestText = rcoH.longestLangData; ci.lenUnpacked = rcoH.tablesSize; ci.lenPacked = 0; if (opts.packHeader == RCO_DATA_COMPRESSION_ZLIB) { uint32_t bound = compressBound (rcoH.tablesSize); bufferOut = (uint8_t *) malloc (bound); ci.lenPacked = zlib_compress (rcoH.tables, rcoH.tablesSize, bufferOut, bound, opts.zlibLevel, opts.zlibMethod); } else if (opts.packHeader == RCO_DATA_COMPRESSION_RLZ) { bufferOut = (uint8_t *) malloc (rcoH.tablesSize); ci.lenPacked = rlz_compress (rcoH.tables, rcoH.tablesSize, bufferOut, rcoH.tablesSize, opts.rlzMode); } else { error ("lulwut?"); exit (1); } int comprMisalign = ci.lenPacked % 4; uint32_t packedLen = ci.lenPacked; if (rco->eSwap) es_headerComprInfo (&ci); filewrite (rcoH.fp, &ci, sizeof (ci)); filewrite (rcoH.fp, bufferOut, packedLen); free (bufferOut); if (comprMisalign) { // 4 byte align uint32_t zero = 0; filewrite (rcoH.fp, &zero, 4 - comprMisalign); } } // write text if packing header if (opts.packText && rco->tblText && rco->tblText->numSubentries) { rRCOEntry *rcoNode; // header.pTextData = rcowrite_ftell(&rcoH); header.pTextData = ftell (rcoH.fp); header.lTextData = 0; // rcoH.sizeText; for (rcoNode = rco->tblText->firstChild; rcoNode; rcoNode = rcoNode->next) { header.lTextData += rco_write_text_resource (&rcoH, rcoNode, opts.packHeader, &opts, ((rRCOTextEntry *) (rcoNode->extra))->lang, (rco->tblText->lastChild == rcoNode)); } } // write resources /* { uint32_t totalPackedLen = 0; if(rco->tblImage) { header.pImgData = * rcowrite_ftell(&rcoH); header.lImgData = rcoH.sizeImg; // TOxDO: this * model actually won't work - we have to update the offsets of ALL the * entries after packing... for(i=0; i<rco->tblImage->numSubentries; i++) { * uint32_t packedSize = rco_write_resource(&rcoH, * &(rco->tblImage->subentries[i]), RCO_DATA_COMPRESSION_NONE); // TOxDO: * change this // TOxDO: update packed size value uint32_t curFpos = * rcowrite_ftell(rcoH.fp); totalPackedLen += (packedSize % 4 ? * (packedSize/4)*4+4 : packedSize); } header.lImgData = totalPackedLen; } * totalPackedLen = 0; if(rco->tblSound) { header.pSoundData = * rcowrite_ftell(&rcoH); header.lSoundData = rcoH.sizeSound; for(i=0; * i<rco->tblSound->numSubentries; i++) { totalPackedLen += * rco_write_resource(&rcoH, &(rco->tblSound->subentries[i]), * RCO_DATA_COMPRESSION_NONE); if(totalPackedLen %4) totalPackedLen += * 4-(totalPackedLen%4); } header.lSoundData = totalPackedLen; } // TOxDO: * write model resources } */ if ((rco->tblImage && rco->tblImage->numSubentries) || (rco->tblSound && rco->tblSound->numSubentries) || (rco->tblModel && rco->tblModel->numSubentries)) { // update data pointers uint32_t pos = ftell (rcoH.fp); if (rco->tblImage && rco->tblImage->numSubentries) { header.pImgData = pos; pos += header.lImgData; } if (rco->tblSound && rco->tblSound->numSubentries) { header.pSoundData = pos; pos += header.lSoundData; } if (rco->tblModel && rco->tblModel->numSubentries) { header.pModelData = pos; pos += header.lModelData; } // copy contents of fTmp across (uses a simple buffered copy) uint32_t len = header.lImgData + header.lSoundData + header.lModelData; uint8_t buffer[65536]; while (len) { uint32_t readAmt = (len > 65536 ? 65536 : len); fileread (fTmp, buffer, readAmt); filewrite (rcoH.fp, buffer, readAmt); len -= readAmt; } fclose (fTmp); // this deletes our temp file } // fix header if (rco->tblVSMX) header.pVSMXTable = rco->tblVSMX->offset; if (rco->tblText) header.pTextTable = rco->tblText->offset; if (rco->tblSound) header.pSoundTable = rco->tblSound->offset; if (rco->tblModel) header.pModelTable = rco->tblModel->offset; if (rco->tblImage) header.pImgTable = rco->tblImage->offset; if (rco->tblFont) header.pFontTable = rco->tblFont->offset; if (rco->tblObj) header.pObjTable = rco->tblObj->offset; if (rco->tblAnim) header.pAnimTable = rco->tblAnim->offset; rewind (rcoH.fp); if (rco->eSwap) es_rcoHeader (&header); filewrite (rcoH.fp, &header, sizeof (header)); // TODO: fix resource pointers? // TODO: tie things up etc?? fclose (rcoH.fp); return TRUE; }
static void put_data(int fd, char *null_buf, const CELL * cell, int row, int n, int zeros_r_nulls) { struct fileinfo *fcb = &R__.fileinfo[fd]; int compressed = fcb->cellhd.compressed; int len = compressed ? sizeof(CELL) : fcb->nbytes; unsigned char *work_buf, *wk; ssize_t nwrite; if (row < 0 || row >= fcb->cellhd.rows) return; if (n <= 0) return; work_buf = G__alloca(fcb->cellhd.cols * sizeof(CELL) + 1); wk = work_buf; if (compressed) set_file_pointer(fd, row); if (compressed) wk++; convert_int(wk, null_buf, cell, n, len, zeros_r_nulls); if (compressed) { unsigned char *wk = work_buf + 1; int nbytes = count_bytes(wk, n, len); unsigned char *compressed_buf; int total; if (fcb->nbytes < nbytes) fcb->nbytes = nbytes; /* first trim away zero high bytes */ if (nbytes < len) trim_bytes(wk, n, len, len - nbytes); total = nbytes * n; compressed_buf = G__alloca(total + 1); compressed_buf[0] = work_buf[0] = nbytes; /* then compress the data */ nwrite = compressed == 1 ? rle_compress(compressed_buf + 1, work_buf + 1, n, nbytes) : zlib_compress(compressed_buf + 1, work_buf + 1, n, nbytes); if (nwrite > 0) { nwrite++; if (write(fd, compressed_buf, nwrite) != nwrite) G_fatal_error(_("Error writing compressed data for row %d of <%s>"), row, fcb->name); } else { nwrite = nbytes * n + 1; if (write(fd, work_buf, nwrite) != nwrite) G_fatal_error(_("Error writing compressed data for row %d of <%s>"), row, fcb->name); } G__freea(compressed_buf); } else { nwrite = fcb->nbytes * n; if (write(fd, work_buf, nwrite) != nwrite) G_fatal_error(_("Error writing uncompressed data for row %d of <%s>"), row, fcb->name); } G__freea(work_buf); }
uint32_t rco_write_text_resource (rRCOFile_writehelper * rcoH, rRCOEntry * entry, uint32_t destCompression, writerco_options * opts, uint32_t lang, uint8_t isLast) { uint32_t len = 0; uint8_t *bufferMid = (uint8_t *) read_resource (entry, &len); if (!bufferMid) return 0; if (len != entry->srcLenUnpacked) { free (bufferMid); return 0; } rRCOTextEntry *extra = (rRCOTextEntry *) (entry->extra); TextComprInfo tci; char *textBuffer = NULL; uint32_t textBufferPos = 0; if (destCompression) { tci.lang = lang; tci.unknown = 1; tci.unpackedLen = 0; // textBuffer = (char*)malloc(1); } uint32_t i; for (i = 0; i < extra->numIndexes; i++) { uint32_t len = extra->indexes[i].length; if (!len) continue; if (destCompression) { tci.unpackedLen += ALIGN_TO_4 (len); textBuffer = (char *) realloc (textBuffer, tci.unpackedLen); memcpy (textBuffer + textBufferPos, bufferMid + extra->indexes[i].offset, len); if (len % 4) { memset (textBuffer + textBufferPos + len, 0, 4 - (len % 4)); } textBufferPos += ALIGN_TO_4 (len); } else { rco_fwrite (rcoH, bufferMid + extra->indexes[i].offset, len); } } free (bufferMid); if (destCompression) { uint8_t success = TRUE; uint8_t *bufferOut = NULL; if (destCompression == RCO_DATA_COMPRESSION_ZLIB) { uint32_t compSize = compressBound (tci.unpackedLen); bufferOut = (uint8_t *) malloc (compSize); tci.packedLen = zlib_compress (textBuffer, tci.unpackedLen, bufferOut, compSize, opts->zlibLevel, opts->zlibMethod); } else if (destCompression == RCO_DATA_COMPRESSION_RLZ) { #ifdef DISABLE_RLZ error ("RLZ compression not supported."); exit (1); #endif bufferOut = (uint8_t *) malloc (tci.unpackedLen); tci.packedLen = rlz_compress (textBuffer, tci.unpackedLen, bufferOut, tci.unpackedLen, opts->rlzMode); } if (!tci.packedLen) { // compression failed free (bufferOut); bufferOut = NULL; success = FALSE; } else if (bufferOut) { if (isLast) tci.nextOffset = 0; else { tci.nextOffset = sizeof (tci) + tci.packedLen; tci.nextOffset = ALIGN_TO_4 (tci.nextOffset); } if (entry->rco->eSwap) es_textComprInfo (&tci); filewrite (rcoH->fp, &tci, sizeof (tci)); if (entry->rco->eSwap) es_textComprInfo (&tci); filewrite (rcoH->fp, bufferOut, tci.packedLen); free (bufferOut); if (tci.packedLen % 4) { uint32_t zero = 0; filewrite (rcoH->fp, &zero, 4 - (tci.packedLen % 4)); } } else success = FALSE; free (textBuffer); if (!success) return 0; return ALIGN_TO_4 (tci.packedLen) + sizeof (tci); } return 1; }