Exemplo n.º 1
0
static bool
check_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;
}
Exemplo n.º 2
0
static bool
sparse_dump_region (struct tar_sparse_file *file, size_t i)
{
  union block *blk;
  off_t bytes_left = file->stat_info->sparse_map[i].numbytes;

  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
    return false;

  while (bytes_left > 0)
    {
      size_t bufsize = (bytes_left > BLOCKSIZE) ? BLOCKSIZE : bytes_left;
      size_t bytes_read;

      blk = find_next_block ();
      bytes_read = safe_read (file->fd, blk->buffer, bufsize);
      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
			      - bytes_left),
			     bufsize);
	  return false;
	}

      memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
      bytes_left -= bytes_read;
      file->dumped_size += bytes_read;
      mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
      set_next_block_after (blk);
    }

  return true;
}
Exemplo n.º 3
0
static bool
check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
{
  if (!lseek_or_error (file, beg, SEEK_SET))
    return false;

  while (beg < end)
    {
      size_t bytes_read;
      size_t rdsize = end - beg;

      if (rdsize > BLOCKSIZE)
	rdsize = BLOCKSIZE;
      clear_block (diff_buffer);
      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))
	{
 	  report_difference (file->stat_info,
			     _("File fragment at %lu is not a hole"), beg);
	  return false;
	}

      beg += bytes_read;
    }
  return true;
}
Exemplo n.º 4
0
/* Scan the sparse file and create its map */
static bool
sparse_scan_file (struct tar_sparse_file *file)
{
  static char buffer[BLOCKSIZE];
  size_t count;
  size_t offset = 0;
  struct sp_array sp = {0, 0};

  if (!lseek_or_error (file, 0, SEEK_SET))
    return false;
  clear_block (buffer);

  file->stat_info->sparse_map_avail = 0;
  file->stat_info->archive_file_size = 0;

  if (!tar_sparse_scan (file, scan_begin, NULL))
    return false;

  while ((count = safe_read (file->fd, buffer, sizeof buffer)) != 0
	 && count != SAFE_READ_ERROR)
    {
      /* Analize the block */
      if (zero_block_p (buffer, count))
	{
	  if (sp.numbytes)
	    {
	      sparse_add_map (file, &sp);
	      sp.numbytes = 0;
	      if (!tar_sparse_scan (file, scan_block, NULL))
		return false;
	    }
	}
      else
	{
	  if (sp.numbytes == 0)
	    sp.offset = offset;
	  sp.numbytes += count;
	  file->stat_info->archive_file_size += count;
	  if (!tar_sparse_scan (file, scan_block, buffer))
	    return false;
	}

      offset += count;
      clear_block (buffer);
    }

  if (sp.numbytes == 0)
    sp.offset = offset;

  sparse_add_map (file, &sp);
  file->stat_info->archive_file_size += count;
  return tar_sparse_scan (file, scan_end, NULL);
}
Exemplo n.º 5
0
static bool
check_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;
}
Exemplo n.º 6
0
static bool
sparse_extract_region (struct tar_sparse_file *file, size_t i)
{
  size_t write_size;

  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
    return false;

  write_size = file->stat_info->sparse_map[i].numbytes;

  if (write_size == 0)
    {
      /* Last block of the file is a hole */
      if (file->seekable && sys_truncate (file->fd))
	truncate_warn (file->stat_info->orig_file_name);
    }
  else while (write_size > 0)
    {
      size_t count;
      size_t wrbytes = (write_size > BLOCKSIZE) ? BLOCKSIZE : write_size;
      union block *blk = find_next_block ();
      if (!blk)
	{
	  ERROR ((0, 0, _("Unexpected EOF in archive")));
	  return false;
	}
      set_next_block_after (blk);
      count = full_write (file->fd, blk->buffer, wrbytes);
      write_size -= count;
      file->dumped_size += count;
      mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
      file->offset += count;
      if (count != wrbytes)
	{
	  write_error_details (file->stat_info->orig_file_name,
			       count, wrbytes);
	  return false;
	}
    }
  return true;
}