📄 xdelta3-main.h
字号:
// Re-encode one windowstatic intmain_recode_func (xd3_stream* stream, main_file *ofile){ int ret; xd3_source decode_source; XD3_ASSERT(stream->dec_state == DEC_FINISH); XD3_ASSERT(recode_stream->enc_state == ENC_INIT || recode_stream->enc_state == ENC_INPUT); // Copy partial decoder output to partial encoder inputs if ((ret = main_recode_copy (recode_stream, DATA_HEAD(recode_stream), &stream->data_sect)) || (ret = main_recode_copy (recode_stream, INST_HEAD(recode_stream), &stream->inst_sect)) || (ret = main_recode_copy (recode_stream, ADDR_HEAD(recode_stream), &stream->addr_sect))) { return ret; } // This jumps to xd3_emit_hdr() recode_stream->enc_state = ENC_FLUSH; recode_stream->avail_in = stream->dec_tgtlen; if (SRCORTGT (stream->dec_win_ind)) { recode_stream->src = & decode_source; decode_source.srclen = stream->dec_cpylen; decode_source.srcbase = stream->dec_cpyoff; } if (option_use_checksum && (stream->dec_win_ind & VCD_ADLER32) != 0) { recode_stream->flags |= XD3_ADLER32_RECODE; recode_stream->recode_adler32 = stream->dec_adler32; } if (option_use_appheader != 0 && option_appheader != NULL) { xd3_set_appheader (recode_stream, option_appheader, strlen ((char*) option_appheader)); } else if (option_use_appheader != 0 && option_appheader == NULL) { if (stream->dec_appheader != NULL) { xd3_set_appheader (recode_stream, stream->dec_appheader, stream->dec_appheadsz); } } // Output loop for (;;) { switch((ret = xd3_encode_input (recode_stream))) { case XD3_INPUT: { /* finished recoding one window */ stream->total_out = recode_stream->total_out; return 0; } case XD3_OUTPUT: { /* main_file_write below */ break; } case XD3_GOTHEADER: case XD3_WINSTART: case XD3_WINFINISH: { /* ignore */ continue; } case XD3_GETSRCBLK: case 0: { return XD3_INTERNAL; } default: return ret; } if ((ret = main_write_output (recode_stream, ofile))) { return ret; } xd3_consume_output (recode_stream); }}#endif /* VCDIFF_TOOLS *//******************************************************************* VCDIFF merging ******************************************************************/#if VCDIFF_TOOLS/* Modifies static state. */static intmain_init_recode_stream (void){ int ret; int stream_flags = XD3_ADLER32_NOVER | XD3_SKIP_EMIT; int recode_flags; xd3_config recode_config; XD3_ASSERT (recode_stream == NULL); if ((recode_stream = (xd3_stream*) main_malloc(sizeof(xd3_stream))) == NULL) { return ENOMEM; } recode_flags = (stream_flags & XD3_SEC_TYPE); recode_config.alloc = main_alloc; recode_config.freef = main_free1; xd3_init_config(&recode_config, recode_flags); if ((ret = main_set_secondary_flags (&recode_config)) || (ret = xd3_config_stream (recode_stream, &recode_config)) || (ret = xd3_encode_init_partial (recode_stream)) || (ret = xd3_whole_state_init (recode_stream))) { XPR(NT XD3_LIB_ERRMSG (recode_stream, ret)); xd3_free_stream (recode_stream); recode_stream = NULL; return ret; } return 0;}/* This processes the sequence of -m arguments. The final input * is processed as part of the ordinary main_input() loop. */static intmain_merge_arguments (main_merge_list* merges){ int ret = 0; int count = 0; main_merge *merge = NULL; xd3_stream merge_input; if (main_merge_list_empty (merges)) { return 0; } if ((ret = xd3_config_stream (& merge_input, NULL)) || (ret = xd3_whole_state_init (& merge_input))) { XPR(NT XD3_LIB_ERRMSG (& merge_input, ret)); return ret; } merge = main_merge_list_front (merges); while (!main_merge_list_end (merges, merge)) { main_file mfile; main_file_init (& mfile); mfile.filename = merge->filename; mfile.flags = RD_NONEXTERNAL; if ((ret = main_file_open (& mfile, merge->filename, XO_READ))) { goto error; } ret = main_input (CMD_MERGE_ARG, & mfile, NULL, NULL); if (ret == 0) { if (count++ == 0) { /* The first merge source is the next merge input. */ xd3_swap_whole_state (& recode_stream->whole_target, & merge_input.whole_target); } else { /* Merge the recode_stream with merge_input. */ ret = xd3_merge_input_output (recode_stream, & merge_input.whole_target); /* Save the next merge source in merge_input. */ xd3_swap_whole_state (& recode_stream->whole_target, & merge_input.whole_target); } } main_file_cleanup (& mfile); if (recode_stream != NULL) { xd3_free_stream (recode_stream); main_free (recode_stream); recode_stream = NULL; } if (main_bdata != NULL) { main_free (main_bdata); main_bdata = NULL; main_bsize = 0; } if (ret != 0) { goto error; } merge = main_merge_list_next (merge); } XD3_ASSERT (merge_stream == NULL); if ((merge_stream = (xd3_stream*) main_malloc (sizeof(xd3_stream))) == NULL) { ret = ENOMEM; goto error; } if ((ret = xd3_config_stream (merge_stream, NULL)) || (ret = xd3_whole_state_init (merge_stream))) { XPR(NT XD3_LIB_ERRMSG (& merge_input, ret)); goto error; } xd3_swap_whole_state (& merge_stream->whole_target, & merge_input.whole_target); ret = 0; error: xd3_free_stream (& merge_input); return ret;}/* This processes each window of the final merge input. This routine * does not output, it buffers the entire delta into memory. */static intmain_merge_func (xd3_stream* stream, main_file *no_write){ int ret; if ((ret = xd3_whole_append_window (stream))) { return ret; } return 0;}/* This is called after all windows have been read, as a final step in * main_input(). This is only called for the final merge step. */static intmain_merge_output (xd3_stream *stream, main_file *ofile){ int ret; usize_t inst_pos = 0; xoff_t output_pos = 0; xd3_source recode_source; usize_t window_num = 0; int at_least_once = 0; /* merge_stream is set if there were arguments. this stream's input * needs to be applied to the merge_stream source. */ if ((merge_stream != NULL) && (ret = xd3_merge_input_output (stream, & merge_stream->whole_target))) { XPR(NT XD3_LIB_ERRMSG (stream, ret)); return ret; } if (option_use_appheader != 0 && option_appheader != NULL) { xd3_set_appheader (recode_stream, option_appheader, strlen ((char*) option_appheader)); } /* Enter the ENC_INPUT state and bypass the next_in == NULL test * and (leftover) input buffering logic. */ XD3_ASSERT(recode_stream->enc_state == ENC_INIT); recode_stream->enc_state = ENC_INPUT; recode_stream->next_in = main_bdata; recode_stream->flags |= XD3_FLUSH; /* This encodes the entire target. */ while (inst_pos < stream->whole_target.instlen || !at_least_once) { xoff_t window_start = output_pos; int window_srcset = 0; xoff_t window_srcmin = 0; xoff_t window_srcmax = 0; usize_t window_pos = 0; usize_t window_size; /* at_least_once ensures that we encode at least one window, * which handles the 0-byte case. */ at_least_once = 1; XD3_ASSERT (recode_stream->enc_state == ENC_INPUT); if ((ret = xd3_encode_input (recode_stream)) != XD3_WINSTART) { XPR(NT "invalid merge state: %s\n", xd3_mainerror (ret)); return XD3_INVALID; } /* Window sizes must match from the input to the output, so that * target copies are in-range (and so that checksums carry * over). */ XD3_ASSERT (window_num < stream->whole_target.wininfolen); window_size = stream->whole_target.wininfo[window_num].length; /* Output position should also match. */ if (output_pos != stream->whole_target.wininfo[window_num].offset) { XPR(NT "internal merge error: offset mismatch\n"); return XD3_INVALID; } if (option_use_checksum && (stream->dec_win_ind & VCD_ADLER32) != 0) { recode_stream->flags |= XD3_ADLER32_RECODE; recode_stream->recode_adler32 = stream->whole_target.wininfo[window_num].adler32; } window_num++; if (main_bsize < window_size) { main_free (main_bdata); main_bdata = NULL; main_bsize = 0; if ((main_bdata = (uint8_t*) main_malloc (window_size)) == NULL) { return ENOMEM; } main_bsize = window_size; } /* This encodes a single target window. */ while (window_pos < window_size && inst_pos < stream->whole_target.instlen) { xd3_winst *inst = &stream->whole_target.inst[inst_pos]; usize_t take = min(inst->size, window_size - window_pos); xoff_t addr; switch (inst->type) { case XD3_RUN: if ((ret = xd3_emit_run (recode_stream, window_pos, take, stream->whole_target.adds[inst->addr]))) { return ret; } break; case XD3_ADD: /* Adds are implicit, put them into the input buffer. */ memcpy (main_bdata + window_pos, stream->whole_target.adds + inst->addr, take); break; default: /* XD3_COPY + copy mode */ if (inst->mode != 0) { if (window_srcset) { window_srcmin = min(window_srcmin, inst->addr); window_srcmax = max(window_srcmax, inst->addr + take); } else { window_srcset = 1; window_srcmin = inst->addr; window_srcmax = inst->addr + take; } addr = inst->addr; } else { XD3_ASSERT (inst->addr >= window_start); addr = inst->addr - window_start; } IF_DEBUG1 (DP(RINT "[merge copy] winpos %u take %u addr %"Q"u mode %u\n", window_pos, take, addr, inst->mode)); if ((ret = xd3_found_match (recode_stream, window_pos, take, addr, inst->mode != 0))) { return ret; } break; } window_pos += take; output_pos += take; if (take == inst->size) { inst_pos += 1; } else { /* Modify the instruction for the next pass. */ if (inst->type != XD3_RUN) { inst->addr += take; } inst->size -= take; } } xd3_avail_input (recode_stream, main_bdata, window_pos); recode_stream->enc_state = ENC_INSTR; if (window_srcset) { recode_stream->srcwin_decided = 1; recode_stream->src = &recode_source; recode_source.srclen = window_srcmax - window_srcmin; recode_source.srcbase = window_srcmin; recode_stream->taroff = recode_source.srclen; } else { recode_stream->srcwin_decided = 0; recode_stream->src = NULL; recode_stream->taroff = 0; } for (;;) { switch ((ret = xd3_encode_input (recode_stream))) { case XD3_INPUT: { goto done_window; } case XD3_OUTPUT: { /* main_file_write below */ break; } case XD3_GOTHEADER: case XD3_WINSTART: case XD3_WINFINISH: { /* ignore */ continue; } case XD3_GETSRCBLK: case 0: { return XD3_INTERNAL; } default: return ret; } if ((ret = main_write_output(recode_stream, ofile))) { return ret; } xd3_consume_output (recode_stream); } done_window: (void) 0; } return 0;}#endif/******************************************************************* Input decompression, output recompression ******************************************************************/#if EXTERNAL_COMPRESSION/* This is tricky POSIX-specific code with lots of fork(), pipe(), * dup(), waitpid(), and exec() business. Most of this code * originated in PRCS1, which did automatic package-file * decompression. It works with both XD3_POSIX and XD3_STDIO file * disciplines. * * To automatically detect compressed inputs requires a child process * to reconstruct the input stream, which was advanced in order to * detect compression, because it may not be seekable. In other * words, the main program reads part of the input stream, and if it * detects a compressed input it then forks a pipe copier process, * which copies the first-read block out of the main-program's memory, * then streams the remaining compressed input into the * input-decompression pipe. */#include <unistd.h>#include <sys/stat.h>#include <sys/wait.h>/* Remember which pipe FD is which. */#define PIPE_READ_FD 0#define PIPE_WRITE_FD 1static pid_t ext_subprocs[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -