⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xdelta3-main.h

📁 Linux下一个可以比较二进制文件的工具xdelta3.0u的源码。
💻 H
📖 第 1 页 / 共 5 页
字号:
static char* ext_tmpfile = NULL;/* Like write(), but makes repeated calls to empty the buffer. */static intmain_pipe_write (int outfd, uint8_t *exist_buf, usize_t remain){  int ret;  if ((ret = xd3_posix_io (outfd, exist_buf, remain,			   (xd3_posix_func*) &write, NULL)))    {      XPR(NT "pipe write failed: %s", xd3_mainerror (ret));      return ret;    }  return 0;}/* A simple error-reporting waitpid interface. */static intmain_waitpid_check(pid_t pid){  int status;  int ret = 0;  if (waitpid (pid, & status, 0) < 0)    {      ret = get_errno ();      XPR(NT "compression subprocess: wait: %s\n", xd3_mainerror (ret));    }  else if (! WIFEXITED (status))    {      ret = ECHILD;      XPR(NT "compression subprocess: signal %d\n",	 WIFSIGNALED (status) ? WTERMSIG (status) : WSTOPSIG (status));    }  else if (WEXITSTATUS (status) != 0)    {      ret = ECHILD;      XPR(NT "compression subprocess: exit %d\n", WEXITSTATUS (status));    }  return ret;}/* Wait for any existing child processes to check for abnormal exit. */static intmain_external_compression_finish (void){  int i;  int ret;  for (i = 0; i < 2; i += 1)    {      if (! ext_subprocs[i]) { continue; }      if ((ret = main_waitpid_check (ext_subprocs[i])))	{	  return ret;	}    }  return 0;}/* This runs as a forked process of main_input_decompress_setup() to * copy input to the decompression process.  First, the available * input is copied out of the existing buffer, then the buffer is * reused to continue reading from the compressed input file. */static intmain_pipe_copier (uint8_t    *pipe_buf,		  usize_t      pipe_bufsize,		  usize_t      nread,		  main_file   *ifile,		  int         outfd){  int ret;  for (;;)    {      if (nread > 0 && (ret = main_pipe_write (outfd, pipe_buf, nread)))	{	  return ret;	}      if (nread < pipe_bufsize)	{	  break;	}      if ((ret = main_file_read (ifile, pipe_buf, pipe_bufsize,				 & nread, "pipe read failed")) < 0)	{	  return ret;	}    }  return 0;}/* This function is called after we have read some amount of data from * the input file and detected a compressed input.  Here we start a * decompression subprocess by forking twice.  The first process runs * the decompression command, the second process copies data to the * input of the first. */static intmain_input_decompress_setup (const main_extcomp     *decomp,			     main_file              *ifile,			     uint8_t               *input_buf,			     usize_t                 input_bufsize,			     uint8_t               *pipe_buf,			     usize_t                 pipe_bufsize,			     usize_t                 pipe_avail,			     usize_t                *nread){  /* The two pipes: input and output file descriptors. */  int outpipefd[2], inpipefd[2];  int input_fd = -1;  /* The resulting input_fd (output of decompression). */  pid_t decomp_id, copier_id;  /* The two subprocs. */  int ret;  outpipefd[0] = outpipefd[1] = -1;  inpipefd[0]  = inpipefd[1]  = -1;  if (pipe (outpipefd) || pipe (inpipefd))    {      XPR(NT "pipe failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }  if ((decomp_id = fork ()) < 0)    {      XPR(NT "fork failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }  /* The first child runs the decompression process: */  if (decomp_id == 0)    {      /* Setup pipes: write to the outpipe, read from the inpipe. */      if (dup2 (outpipefd[PIPE_WRITE_FD], STDOUT_FILENO) < 0 ||	  dup2 (inpipefd[PIPE_READ_FD], STDIN_FILENO) < 0 ||	  close (outpipefd[PIPE_READ_FD]) ||	  close (outpipefd[PIPE_WRITE_FD]) ||	  close (inpipefd[PIPE_READ_FD]) ||	  close (inpipefd[PIPE_WRITE_FD]) ||	  execlp (decomp->decomp_cmdname, decomp->decomp_cmdname,		  decomp->decomp_options, NULL))	{	  XPR(NT "child process %s failed to execute: %s\n",	      decomp->decomp_cmdname, xd3_mainerror (get_errno ()));	}      _exit (127);    }  ext_subprocs[0] = decomp_id;  if ((copier_id = fork ()) < 0)    {      XPR(NT "fork failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }  /* The second child runs the copier process: */  if (copier_id == 0)    {      int exitval = 0;      if (close (inpipefd[PIPE_READ_FD]) ||	  main_pipe_copier (pipe_buf, pipe_bufsize, pipe_avail,			    ifile, inpipefd[PIPE_WRITE_FD]) ||	  close (inpipefd[PIPE_WRITE_FD]))	{	  XPR(NT "child copier process failed: %s\n",	      xd3_mainerror (get_errno ()));	  exitval = 1;	}      _exit (exitval);    }  ext_subprocs[1] = copier_id;  /* The parent closes both pipes after duplicating the output of   * compression. */  input_fd = dup (outpipefd[PIPE_READ_FD]);  if (input_fd < 0 ||      main_file_close (ifile) ||      close (outpipefd[PIPE_READ_FD]) ||      close (outpipefd[PIPE_WRITE_FD]) ||      close (inpipefd[PIPE_READ_FD]) ||      close (inpipefd[PIPE_WRITE_FD]))    {      XPR(NT "dup/close failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }#if XD3_STDIO  /* Note: fdopen() acquires the fd, closes it when finished. */  if ((ifile->file = fdopen (input_fd, "r")) == NULL)    {      XPR(NT "fdopen failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }#elif XD3_POSIX  ifile->file = input_fd;#endif  ifile->compressor = decomp;  /* Now the input file is decompressed. */  return main_file_read (ifile, input_buf, input_bufsize,			 nread, "input decompression failed"); pipe_cleanup:  close (input_fd);  close (outpipefd[PIPE_READ_FD]);  close (outpipefd[PIPE_WRITE_FD]);  close (inpipefd[PIPE_READ_FD]);  close (inpipefd[PIPE_WRITE_FD]);  return ret;}/* This routine is called when the first buffer of input data is read * by the main program (unless input decompression is disabled by * command-line option).  If it recognizes the magic number of a known * input type it invokes decompression. * * Skips decompression if the decompression type or the file type is * RD_NONEXTERNAL. * * Behaves exactly like main_file_read, otherwise. * * This function uses a separate buffer to read the first small block * of input.  If a compressed input is detected, the separate buffer * is passed to the pipe copier.  This avoids using the same size * buffer in both cases. */static intmain_decompress_input_check (main_file   *ifile,			    uint8_t    *input_buf,			    usize_t      input_size,			    usize_t     *nread){  int ret;  usize_t i;  usize_t check_nread;  uint8_t check_buf[XD3_ALLOCSIZE];  if ((ret = main_file_read (ifile, check_buf,			     min (input_size, XD3_ALLOCSIZE),			     & check_nread, "input read failed")))    {      return ret;    }  for (i = 0; i < SIZEOF_ARRAY (extcomp_types); i += 1)    {      const main_extcomp *decomp = & extcomp_types[i];      if ((check_nread > decomp->magic_size) &&	  /* The following expr skips decompression if we are trying	   * to read a VCDIFF input and that is the magic number. */	  !((decomp->flags & RD_NONEXTERNAL) &&	    (ifile->flags & RD_NONEXTERNAL)) &&	  memcmp (check_buf, decomp->magic, decomp->magic_size) == 0)	{	  if (! option_quiet)	    {	      XPR(NT "%s | %s %s\n",		 ifile->filename,		 decomp->decomp_cmdname,		 decomp->decomp_options);	    }	  return main_input_decompress_setup (decomp, ifile,					      input_buf, input_size,					      check_buf, XD3_ALLOCSIZE,					      check_nread, nread);	}    }  /* Now read the rest of the input block. */  (*nread) = 0;  if (check_nread == XD3_ALLOCSIZE)    {      ret = main_file_read (ifile, input_buf + XD3_ALLOCSIZE,			    input_size - XD3_ALLOCSIZE, nread,			    "input read failed");    }  memcpy (input_buf, check_buf, check_nread);  (*nread) += check_nread;  return 0;}/* This is called when the source file needs to be decompressed.  We * fork/exec a decompression command with the proper input and output * to a temporary file. */static intmain_decompress_source (main_file *sfile, xd3_source *source){  const main_extcomp *decomp = sfile->compressor;  pid_t decomp_id;  /* One subproc. */  int   input_fd  = -1;  int   output_fd = -1;  int   ret;  char *tmpname = NULL;  char *tmpdir  = getenv ("TMPDIR");  static const char tmpl[] = "/xd3src.XXXXXX";  /* Make a template for mkstmp() */  if (tmpdir == NULL) { tmpdir = "/tmp"; }  if ((tmpname =       (char*) main_malloc (strlen (tmpdir) + sizeof (tmpl) + 1)) == NULL)    {      return ENOMEM;    }  sprintf (tmpname, "%s%s", tmpdir, tmpl);  XD3_ASSERT (ext_tmpfile == NULL);  ext_tmpfile = tmpname;  /* Open the output FD. */  if ((output_fd = mkstemp (tmpname)) < 0)    {      XPR(NT "mkstemp failed: %s: %s",	  tmpname, xd3_mainerror (ret = get_errno ()));      goto cleanup;    }  /* Copy the input FD, reset file position. */  XD3_ASSERT (main_file_isopen (sfile));#if XD3_STDIO  if ((input_fd = dup (fileno (sfile->file))) < 0)    {      XPR(NT "dup failed: %s", xd3_mainerror (ret = get_errno ()));      goto cleanup;    }  main_file_close (sfile);  sfile->file = NULL;#elif XD3_POSIX  input_fd = sfile->file;  sfile->file = -1;#endif  if ((ret = lseek (input_fd, SEEK_SET, 0)) != 0)    {      XPR(NT "lseek failed: : %s", xd3_mainerror (ret = get_errno ()));      goto cleanup;    }  if ((decomp_id = fork ()) < 0)    {      XPR(NT "fork failed: %s", xd3_mainerror (ret = get_errno ()));      goto cleanup;    }  /* The child runs the decompression process: */  if (decomp_id == 0)    {      /* Setup pipes: write to the output file, read from the pipe. */      if (dup2 (input_fd, STDIN_FILENO) < 0 ||	  dup2 (output_fd, STDOUT_FILENO) < 0 ||	  execlp (decomp->decomp_cmdname, decomp->decomp_cmdname,		  decomp->decomp_options, NULL))	{	  XPR(NT "child process %s failed to execute: %s\n",		   decomp->decomp_cmdname, xd3_mainerror (get_errno ()));	}      _exit (127);    }  close (input_fd);  close (output_fd);  input_fd  = -1;  output_fd = -1;  /* Then wait for completion. */  if ((ret = main_waitpid_check (decomp_id)))    {      goto cleanup;    }  /* Open/stat the decompressed source file. */  if ((ret = main_file_open (sfile, tmpname, XO_READ))) { goto cleanup; }  if ((ret = main_file_stat (sfile, & source->size, 1))) { goto cleanup; }  return 0; cleanup:  close (input_fd);  close (output_fd);  if (tmpname) { free (tmpname); }  ext_tmpfile = NULL;  return ret;}/* Initiate re-compression of the output stream.  This is easier than * input decompression because we know beforehand that the stream will * be compressed, whereas the input has already been read when we * decide it should be decompressed.  Thus, it only requires one * subprocess and one pipe. */static intmain_recompress_output (main_file *ofile){  pid_t recomp_id;  /* One subproc. */  int   pipefd[2];  /* One pipe. */  int   output_fd = -1;  int   ret;  const main_extcomp *recomp = ofile->compressor;  pipefd[0] = pipefd[1] = -1;  if (pipe (pipefd))    {      XPR(NT "pipe failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }  if ((recomp_id = fork ()) < 0)    {      XPR(NT "fork failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }  /* The child runs the recompression process: */  if (recomp_id == 0)    {      /* Setup pipes: write to the output file, read from the pipe. */      if (dup2 (XFNO (ofile), STDOUT_FILENO) < 0 ||	  dup2 (pipefd[PIPE_READ_FD], STDIN_FILENO) < 0 ||	  close (pipefd[PIPE_READ_FD]) ||	  close (pipefd[PIPE_WRITE_FD]) ||	  execlp (recomp->recomp_cmdname, recomp->recomp_cmdname,		  recomp->recomp_options, NULL))	{	  XPR(NT "child process %s failed to execute: %s\n",	      recomp->recomp_cmdname, xd3_mainerror (get_errno ()));	}      _exit (127);    }  ext_subprocs[0] = recomp_id;  /* The parent closes both pipes after duplicating the output-fd for   * writing to the compression pipe. */  output_fd = dup (pipefd[PIPE_WRITE_FD]);  if (output_fd < 0 ||      main_file_close (ofile) ||      close (pipefd[PIPE_READ_FD]) ||      close (pipefd[PIPE_WRITE_FD]))    {      XPR(NT "close failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }#if XD3_STDIO  /* Note: fdopen() acquires the fd, closes it when finished. */  if ((ofile->file = fdopen (output_fd, "w")) == NULL)    {      XPR(NT "fdopen failed: %s\n", xd3_mainerror (ret = get_errno ()));      goto pipe_cleanup;    }#elif XD3_POSIX  ofile->file = output_fd;#endif  /* Now the output file will be compressed. */  return 0; pipe_cleanup:  close (output_fd);  close (pipefd[PIPE_READ_FD]);  close (pipefd[PIPE_WRITE_FD]);  return ret;}#endif /* EXTERNAL_COMPRESSION *//* Identify the compressor that was used based on its ident string, * which is passed in the application header. */static const main_extcomp*main_ident_compressor (const char *ident){  usize_t i;  for (i = 0; i < SIZEOF_ARRAY (extcomp_types); i += 1)    {      if (strcmp (extcomp_types[i].ident, ident) == 0)	{	  return & extcomp_types[i];	}    }  return NULL;}/* Return the main_ex

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -