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

📄 sparse.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 3 页
字号:
  if (rc && file.optab->dump_region)    {      tar_sparse_dump_header (&file);      if (fd >= 0)	{	  size_t i;	  mv_begin (file.stat_info);	  for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)	    rc = tar_sparse_dump_region (&file, i);	  mv_end ();	}    }  pad_archive (file.stat_info->archive_file_size - file.dumped_size);  return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;}boolsparse_member_p (struct tar_stat_info *st){  struct tar_sparse_file file;  if (!tar_sparse_init (&file))    return false;  file.stat_info = st;  return tar_sparse_member_p (&file);}boolsparse_fixup_header (struct tar_stat_info *st){  struct tar_sparse_file file;  if (!tar_sparse_init (&file))    return false;  file.stat_info = st;  return tar_sparse_fixup_header (&file);}enum dump_statussparse_extract_file (int fd, struct tar_stat_info *st, off_t *size){  bool rc = true;  struct tar_sparse_file file;  size_t i;  if (!tar_sparse_init (&file))    return dump_status_not_implemented;  file.stat_info = st;  file.fd = fd;  file.seekable = lseek (fd, 0, SEEK_SET) == 0;  file.offset = 0;  rc = tar_sparse_decode_header (&file);  for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)    rc = tar_sparse_extract_region (&file, i);  *size = file.stat_info->archive_file_size - file.dumped_size;  return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;}enum dump_statussparse_skip_file (struct tar_stat_info *st){  bool rc = true;  struct tar_sparse_file file;  if (!tar_sparse_init (&file))    return dump_status_not_implemented;  file.stat_info = st;  file.fd = -1;  rc = tar_sparse_decode_header (&file);  skip_file (file.stat_info->archive_file_size - file.dumped_size);  return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;}static boolcheck_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end){  if (!lseek_or_error (file, beg))    return false;  while (beg < end)    {      size_t bytes_read;      size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;      char diff_buffer[BLOCKSIZE];      bytes_read = safe_read (file->fd, diff_buffer, rdsize);      if (bytes_read == SAFE_READ_ERROR)	{          read_diag_details (file->stat_info->orig_file_name,	                     beg,			     rdsize);	  return false;	}      if (!zero_block_p (diff_buffer, bytes_read))	{	  char begbuf[INT_BUFSIZE_BOUND (off_t)]; 	  report_difference (file->stat_info,			     _("File fragment at %s is not a hole"),			     offtostr (beg, begbuf));	  return false;	}      beg += bytes_read;    }  return true;}static boolcheck_data_region (struct tar_sparse_file *file, size_t i){  size_t size_left;  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))    return false;  size_left = file->stat_info->sparse_map[i].numbytes;  mv_size_left (file->stat_info->archive_file_size - file->dumped_size);        while (size_left > 0)    {      size_t bytes_read;      size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;      char diff_buffer[BLOCKSIZE];      union block *blk = find_next_block ();      if (!blk)	{	  ERROR ((0, 0, _("Unexpected EOF in archive")));	  return false;	}      set_next_block_after (blk);      bytes_read = safe_read (file->fd, diff_buffer, rdsize);      if (bytes_read == SAFE_READ_ERROR)	{          read_diag_details (file->stat_info->orig_file_name,			     (file->stat_info->sparse_map[i].offset			      + file->stat_info->sparse_map[i].numbytes			      - size_left),			     rdsize);	  return false;	}      file->dumped_size += bytes_read;      size_left -= bytes_read;      mv_size_left (file->stat_info->archive_file_size - file->dumped_size);      if (memcmp (blk->buffer, diff_buffer, rdsize))	{	  report_difference (file->stat_info, _("Contents differ"));	  return false;	}    }  return true;}boolsparse_diff_file (int fd, struct tar_stat_info *st){  bool rc = true;  struct tar_sparse_file file;  size_t i;  off_t offset = 0;  if (!tar_sparse_init (&file))    return dump_status_not_implemented;  file.stat_info = st;  file.fd = fd;  file.seekable = true; /* File *must* be seekable for compare to work */    rc = tar_sparse_decode_header (&file);  mv_begin (st);  for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)    {      rc = check_sparse_region (&file,				offset, file.stat_info->sparse_map[i].offset)	    && check_data_region (&file, i);      offset = file.stat_info->sparse_map[i].offset	        + file.stat_info->sparse_map[i].numbytes;    }  if (!rc)    skip_file (file.stat_info->archive_file_size - file.dumped_size);  mv_end ();    tar_sparse_done (&file);  return rc;}/* Old GNU Format. The sparse file information is stored in the   oldgnu_header in the following manner:   The header is marked with type 'S'. Its `size' field contains   the cumulative size of all non-empty blocks of the file. The   actual file size is stored in `realsize' member of oldgnu_header.   The map of the file is stored in a list of `struct sparse'.   Each struct contains offset to the block of data and its   size (both as octal numbers). The first file header contains   at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map   contains more structs, then the field `isextended' of the main   header is set to 1 (binary) and the `struct sparse_header'   header follows, containing at most 21 following structs   (SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'   field of the extended header is set and next  next extension header   follows, etc... */enum oldgnu_add_status  {    add_ok,    add_finish,    add_fail  };static boololdgnu_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused))){  return current_header->header.typeflag == GNUTYPE_SPARSE;}/* Add a sparse item to the sparse file and its obstack */static enum oldgnu_add_statusoldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s){  struct sp_array sp;  if (s->numbytes[0] == '\0')    return add_finish;  sp.offset = OFF_FROM_HEADER (s->offset);  sp.numbytes = SIZE_FROM_HEADER (s->numbytes);  if (sp.offset < 0      || file->stat_info->stat.st_size < sp.offset + sp.numbytes      || file->stat_info->archive_file_size < 0)    return add_fail;  sparse_add_map (file->stat_info, &sp);  return add_ok;}static boololdgnu_fixup_header (struct tar_sparse_file *file){  /* NOTE! st_size was initialized from the header     which actually contains archived size. The following fixes it */  file->stat_info->archive_file_size = file->stat_info->stat.st_size;  file->stat_info->stat.st_size =    OFF_FROM_HEADER (current_header->oldgnu_header.realsize);  return true;}/* Convert old GNU format sparse data to internal representation */static boololdgnu_get_sparse_info (struct tar_sparse_file *file){  size_t i;  union block *h = current_header;  int ext_p;  enum oldgnu_add_status rc;  file->stat_info->sparse_map_avail = 0;  for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)    {      rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);      if (rc != add_ok)	break;    }  for (ext_p = h->oldgnu_header.isextended;       rc == add_ok && ext_p; ext_p = h->sparse_header.isextended)    {      h = find_next_block ();      if (!h)	{	  ERROR ((0, 0, _("Unexpected EOF in archive")));	  return false;	}      set_next_block_after (h);      for (i = 0; i < SPARSES_IN_SPARSE_HEADER && rc == add_ok; i++)	rc = oldgnu_add_sparse (file, &h->sparse_header.sp[i]);    }  if (rc == add_fail)    {      ERROR ((0, 0, _("%s: invalid sparse archive member"),	      file->stat_info->orig_file_name));      return false;    }  return true;}static voidoldgnu_store_sparse_info (struct tar_sparse_file *file, size_t *pindex,			  struct sparse *sp, size_t sparse_size){  for (; *pindex < file->stat_info->sparse_map_avail	 && sparse_size > 0; sparse_size--, sp++, ++*pindex)    {      OFF_TO_CHARS (file->stat_info->sparse_map[*pindex].offset,		    sp->offset);      SIZE_TO_CHARS (file->stat_info->sparse_map[*pindex].numbytes,		     sp->numbytes);    }}static boololdgnu_dump_header (struct tar_sparse_file *file){  off_t block_ordinal = current_block_ordinal ();  union block *blk;  size_t i;  blk = start_header (file->stat_info);  blk->header.typeflag = GNUTYPE_SPARSE;  if (file->stat_info->sparse_map_avail > SPARSES_IN_OLDGNU_HEADER)    blk->oldgnu_header.isextended = 1;  /* Store the real file size */  OFF_TO_CHARS (file->stat_info->stat.st_size, blk->oldgnu_header.realsize);  /* Store the effective (shrunken) file size */  OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);  i = 0;  oldgnu_store_sparse_info (file, &i,			    blk->oldgnu_header.sp,			    SPARSES_IN_OLDGNU_HEADER);  blk->oldgnu_header.isextended = i < file->stat_info->sparse_map_avail;  finish_header (file->stat_info, blk, block_ordinal);  while (i < file->stat_info->sparse_map_avail)    {      blk = find_next_block ();      memset (blk->buffer, 0, BLOCKSIZE);      oldgnu_store_sparse_info (file, &i,				blk->sparse_header.sp,				SPARSES_IN_SPARSE_HEADER);      if (i < file->stat_info->sparse_map_avail)	blk->sparse_header.isextended = 1;      set_next_block_after (blk);    }  return true;}static struct tar_sparse_optab const oldgnu_optab = {  NULL,  /* No init function */  NULL,  /* No done function */  oldgnu_sparse_member_p,  oldgnu_dump_header,  oldgnu_fixup_header,  oldgnu_get_sparse_info,  NULL,  /* No scan_block function */  sparse_dump_region,  sparse_extract_region,};/* Star */static boolstar_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused))){  return current_header->header.typeflag == GNUTYPE_SPARSE;}static boolstar_fixup_header (struct tar_sparse_file *file){  /* NOTE! st_size was initialized from the header     which actually contains archived size. The following fixes it */  file->stat_info->archive_file_size = file->stat_info->stat.st_size;  file->stat_info->stat.st_size =            OFF_FROM_HEADER (current_header->star_in_header.realsize);  return true;}/* Convert STAR format sparse data to internal representation */static boolstar_get_sparse_info (struct tar_sparse_file *file){  size_t i;  union block *h = current_header;  int ext_p;  enum oldgnu_add_status rc = add_ok;  file->stat_info->sparse_map_avail = 0;  if (h->star_in_header.prefix[0] == '\0'

⌨️ 快捷键说明

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