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

📄 xdelta3-main.h

📁 Linux下一个可以比较二进制文件的工具xdelta3.0u的源码。
💻 H
📖 第 1 页 / 共 5 页
字号:
get_errno (void){#ifndef _WIN32  if (errno == 0)    {      XPR(NT "you found a bug: expected errno != 0\n");      errno = XD3_INTERNAL;    }  return errno;#else  DWORD errNum = GetLastError();  if (errNum == NO_ERROR) {	  errNum = XD3_INTERNAL;  }  return errNum;#endif}const char*xd3_mainerror(int err_num) {#ifndef _WIN32	const char* x = xd3_strerror (err_num);	if (x != NULL) {		return x;	}	return strerror(err_num);#else	static char err_buf[256];	const char* x = xd3_strerror (err_num);	if (x != NULL) {		return x;	}	memset (err_buf, 0, 256);	FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |		       FORMAT_MESSAGE_IGNORE_INSERTS,		NULL, err_num,		MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),		err_buf, 256, NULL);	return err_buf;#endif}static longget_millisecs_now (void){#ifndef _WIN32  struct timeval tv;  gettimeofday (& tv, NULL);  return (tv.tv_sec) * 1000L + (tv.tv_usec) / 1000;#else  SYSTEMTIME st;  FILETIME ft;  __int64 *pi = (__int64*)&ft;  GetLocalTime(&st);  SystemTimeToFileTime(&st, &ft);  return (long)((*pi) / 10000);#endif}/* Always >= 1 millisec, right? */static longget_millisecs_since (void){  static long last = 0;  long now = get_millisecs_now();  long diff = now - last;  last = now;  return diff;}static char*main_format_bcnt (xoff_t r, char *buf){  static const char* fmts[] = { "B", "KB", "MB", "GB" };  usize_t i;  for (i = 0; i < SIZEOF_ARRAY(fmts); i += 1)    {      if (r <= (10 * 1024) || i == (-1 + (int)SIZEOF_ARRAY(fmts)))	{	  sprintf (buf, "%"Q"u %s", r, fmts[i]);	  break;	}      r /= 1024;    }  return buf;}static char*main_format_rate (xoff_t bytes, long millis, char *buf){  xoff_t r = (xoff_t)(1.0 * bytes / (1.0 * millis / 1000.0));  static char lbuf[32];  main_format_bcnt (r, lbuf);  sprintf (buf, "%s/sec", lbuf);  return buf;}static char*main_format_millis (long millis, char *buf){  if (millis < 1000)       { sprintf (buf, "%lu ms", millis); }  else if (millis < 10000) { sprintf (buf, "%.1f sec", millis / 1000.0); }  else                     { sprintf (buf, "%lu sec", millis / 1000L); }  return buf;}/* A safe version of strtol for xoff_t. */static intmain_strtoxoff (const char* s, xoff_t *xo, char which){  char *e;  xoff_t x;  XD3_ASSERT(s && *s != 0);  {    /* Should check LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX? */#if SIZEOF_XOFF_T == 4    long xx = strtol (s, &e, 0);#else    long long xx = strtoll (s, &e, 0);#endif    if (xx < 0)      {	XPR(NT "-%c: negative integer: %s\n", which, s);	return EXIT_FAILURE;      }    x = xx;  }  if (*e != 0)    {      XPR(NT "-%c: invalid integer: %s\n", which, s);      return EXIT_FAILURE;    }  (*xo) = x;  return 0;}static intmain_atou (const char* arg, usize_t *xo, usize_t low,	   usize_t high, char which){  xoff_t x;  int ret;  if ((ret = main_strtoxoff (arg, & x, which))) { return ret; }  if (x < low)    {      XPR(NT "-%c: minimum value: %u\n", which, low);      return EXIT_FAILURE;    }  if (high == 0)    {      high = USIZE_T_MAX;    }  if (x > high)    {      XPR(NT "-%c: maximum value: %u\n", which, high);      return EXIT_FAILURE;    }  (*xo) = (usize_t)x;  return 0;}/****************************************************************** FILE BASICS ******************************************************************//* With all the variation in file system-call semantics, arguments, * return values and error-handling for the POSIX and STDIO file APIs, * the insides of these functions make me sick, which is why these * wrappers exist. */#define XOPEN_OPNAME (xfile->mode == XO_READ ? "read" : "write")#define XOPEN_STDIO  (xfile->mode == XO_READ ? "rb" : "wb")#define XOPEN_POSIX  (xfile->mode == XO_READ ? \		      O_RDONLY : O_WRONLY | O_CREAT | O_TRUNC)#define XOPEN_MODE   (xfile->mode == XO_READ ? 0 : 0666)#define XF_ERROR(op, name, ret) \  do { if (!option_quiet) { XPR(NT "file %s failed: %s: %s: %s\n", (op), \       XOPEN_OPNAME, (name), xd3_mainerror (ret)); } } while (0)#if XD3_STDIO#define XFNO(f) fileno(f->file)#define XSTDOUT_XF(f) { (f)->file = stdout; (f)->filename = "/dev/stdout"; }#define XSTDIN_XF(f)  { (f)->file = stdin;  (f)->filename = "/dev/stdin"; }#elif XD3_POSIX#define XFNO(f) f->file#define XSTDOUT_XF(f) \  { (f)->file = STDOUT_FILENO; (f)->filename = "/dev/stdout"; }#define XSTDIN_XF(f) \  { (f)->file = STDIN_FILENO;  (f)->filename = "/dev/stdin"; }#elif XD3_WIN32#define XFNO(f) -1#define XSTDOUT_XF(f) { \  (f)->file = GetStdHandle(STD_OUTPUT_HANDLE); \  (f)->filename = "(stdout)"; \  }#define XSTDIN_XF(f) { \  (f)->file = GetStdHandle(STD_INPUT_HANDLE); \  (f)->filename = "(stdin)"; \  }#endifstatic voidmain_file_init (main_file *xfile){  memset (xfile, 0, sizeof (*xfile));#if XD3_POSIX  xfile->file = -1;#endif#if XD3_WIN32  xfile->file = INVALID_HANDLE_VALUE;#endif}static intmain_file_isopen (main_file *xfile){#if XD3_STDIO  return xfile->file != NULL;#elif XD3_POSIX  return xfile->file != -1;#elif XD3_WIN32  return xfile->file != INVALID_HANDLE_VALUE;#endif}static intmain_file_close (main_file *xfile){  int ret = 0;  if (! main_file_isopen (xfile))    {      return 0;    }#if XD3_STDIO  ret = fclose (xfile->file);  xfile->file = NULL;#elif XD3_POSIX  ret = close (xfile->file);  xfile->file = -1;#elif XD3_WIN32  if (!CloseHandle(xfile->file)) {    ret = get_errno ();  }  xfile->file = INVALID_HANDLE_VALUE;#endif  if (ret != 0) { XF_ERROR ("close", xfile->filename, ret = get_errno ()); }  return ret;}static voidmain_file_cleanup (main_file *xfile){  XD3_ASSERT (xfile != NULL);  if (main_file_isopen (xfile))    {      main_file_close (xfile);    }  if (xfile->snprintf_buf != NULL)    {      main_free(xfile->snprintf_buf);      xfile->snprintf_buf = NULL;    }  if (xfile->filename_copy != NULL)    {      main_free(xfile->filename_copy);      xfile->filename_copy = NULL;    }}static intmain_file_open (main_file *xfile, const char* name, int mode){  int ret = 0;  xfile->mode = mode;  XD3_ASSERT (name != NULL);  XD3_ASSERT (! main_file_isopen (xfile));  if (name[0] == 0)    {      XPR(NT "invalid file name: empty string\n");      return XD3_INVALID;    }#if XD3_STDIO  xfile->file = fopen (name, XOPEN_STDIO);  ret = (xfile->file == NULL) ? get_errno () : 0;#elif XD3_POSIX  if ((ret = open (name, XOPEN_POSIX, XOPEN_MODE)) < 0)    {      ret = get_errno ();    }  else    {      xfile->file = ret;      ret = 0;    }#elif XD3_WIN32  xfile->file = CreateFile(name,	  (mode == XO_READ) ? GENERIC_READ : GENERIC_WRITE,	  FILE_SHARE_READ,	  NULL,	  (mode == XO_READ) ? OPEN_EXISTING :			   (option_force ? CREATE_ALWAYS : CREATE_NEW),	  FILE_ATTRIBUTE_NORMAL,	  NULL);  if (xfile->file == INVALID_HANDLE_VALUE) {	  ret = get_errno ();  }#endif  if (ret) { XF_ERROR ("open", name, ret); }  else     { xfile->realname = name; xfile->nread = 0; }  return ret;}static intmain_file_stat (main_file *xfile, xoff_t *size, int err_ifnoseek){  int ret = 0;#if XD3_WIN32# if (_WIN32_WINNT >= 0x0500)  LARGE_INTEGER li;  if (GetFileSizeEx(xfile->file, &li) == 0)    {      ret = get_errno ();    }  else    {      *size = li.QuadPart;    }# else  DWORD filesize = GetFileSize(xfile->file, NULL);  if (filesize == INVALID_FILE_SIZE)    {      ret = GetLastError();      if (ret != NO_ERROR)	return ret;    }  *size = filesize;# endif#else  struct stat sbuf;  if (fstat (XFNO (xfile), & sbuf) < 0)    {      ret = get_errno ();      if (err_ifnoseek)	{	  XF_ERROR ("stat", xfile->filename, ret);	}      return ret;    }  if (! S_ISREG (sbuf.st_mode))    {      if (err_ifnoseek)	{	  XPR(NT "source file must be seekable: %s\n", xfile->filename);	}      return ESPIPE;    }  (*size) = sbuf.st_size;#endif  return ret;}static intmain_file_exists (main_file *xfile){  struct stat sbuf;  return stat (xfile->filename, & sbuf) == 0 && S_ISREG (sbuf.st_mode);}#if (XD3_POSIX || EXTERNAL_COMPRESSION)/* POSIX-generic code takes a function pointer to read() or write(). * This calls the function repeatedly until the buffer is full or EOF. * The NREAD parameter is not set for write, NULL is passed.  Return * is signed, < 0 indicate errors, otherwise byte count. */typedef int (xd3_posix_func) (int fd, uint8_t *buf, usize_t size);static intxd3_posix_io (int fd, uint8_t *buf, usize_t size,	      xd3_posix_func *func, usize_t *nread){  int ret;  usize_t nproc = 0;  while (nproc < size)    {      int result = (*func) (fd, buf + nproc, size - nproc);      if (result < 0)	{	  ret = get_errno ();	  if (ret != EAGAIN && ret != EINTR)	    {	      return ret;	    }	  result = 0;	}      if (nread != NULL && result == 0) { break; }      nproc += result;    }  if (nread != NULL) { (*nread) = nproc; }  return 0;}#endif/* POSIX is unbuffered, while STDIO is buffered.  main_file_read() * should always be called on blocks. */static intmain_file_read (main_file   *ifile,	       uint8_t    *buf,	       usize_t      size,	       usize_t     *nread,	       const char *msg){  int ret = 0;#if XD3_STDIO  usize_t result;  result = fread (buf, 1, size, ifile->file);  if (result < size && ferror (ifile->file))    {      ret = get_errno ();    }  else    {      *nread = result;    }#elif XD3_POSIX  ret = xd3_posix_io (ifile->file, buf, size, (xd3_posix_func*) &read, nread);#elif XD3_WIN32  DWORD nread2;  if (ReadFile (ifile->file, buf, size, &nread2, NULL) == 0) {	  ret = get_errno();  } else {      *nread = (usize_t)nread2;  }#endif  if (ret)    {      XPR(NT "%s: %s: %s\n", msg, ifile->filename, xd3_mainerror (ret));    }  else    {      if (option_verbose > 3) { XPR(NT "main read: %s: %u\n",				    ifile->filename, (*nread)); }      ifile->nread += (*nread);    }  return ret;}static intmain_file_write (main_file *ofile, uint8_t *buf, usize_t size, const char *msg){  int ret = 0;#if XD3_STDIO  usize_t result;  result = fwrite (buf, 1, size, ofile->file);  if (result != size) { ret = get_errno (); }#elif XD3_POSIX  ret = xd3_posix_io (ofile->file, buf, size, (xd3_posix_func*) &write, NULL);#elif XD3_WIN32  DWORD nwrite;  if (WriteFile(ofile->file, buf, size, &nwrite, NULL) == 0) {	  ret = get_errno ();  } else {

⌨️ 快捷键说明

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