/[tar]/tar/src/sparse.c
ViewVC logotype

Diff of /tar/src/sparse.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by gray, Mon Nov 17 07:32:37 2003 UTC revision 1.2 by gray, Mon Nov 17 11:04:16 2003 UTC
# Line 130  zero_block_p (char *buffer, size_t size) Line 130  zero_block_p (char *buffer, size_t size)
130  {  {
131    while (size--)    while (size--)
132      if (*buffer++)      if (*buffer++)
133        return 0;        return false;
134    return 1;    return true;
135  }  }
136    
137  #define clear_block(p) memset (p, 0, BLOCKSIZE);  #define clear_block(p) memset (p, 0, BLOCKSIZE);
# Line 374  sparse_extract_file (int fd, struct tar_ Line 374  sparse_extract_file (int fd, struct tar_
374    return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;    return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
375  }  }
376    
377    
378    static char diff_buffer[BLOCKSIZE];
379                      
380    static bool
381    check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
382    {
383      if (!lseek_or_error (file, beg, SEEK_SET))
384        return false;
385      
386      while (beg < end)
387        {
388          size_t bytes_read;
389          size_t rdsize = end - beg;
390          
391          if (rdsize > BLOCKSIZE)
392            rdsize = BLOCKSIZE;
393          clear_block (diff_buffer);
394          bytes_read = safe_read (file->fd, diff_buffer, rdsize);
395          if (bytes_read < 0)
396            {
397              read_diag_details (file->stat_info->orig_file_name,
398                                 beg,
399                                 rdsize);
400              return false;
401            }
402          if (!zero_block_p (diff_buffer, bytes_read))
403            {
404              report_difference (file->stat_info,
405                                 _("File fragment at %lu is not a hole"), beg);
406              return false;
407            }
408    
409          beg += bytes_read;
410        }
411      return true;
412    }
413    
414    static bool
415    check_data_region (struct tar_sparse_file *file, size_t index)
416    {
417      size_t size_left;
418      
419      if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
420                           SEEK_SET))
421        return false;
422      size_left = file->stat_info->sparse_map[index].numbytes;
423      while (size_left > 0)
424        {
425          size_t bytes_read;
426          size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
427          
428          union block *blk = find_next_block ();
429          if (!blk)
430            {
431              ERROR ((0, 0, _("Unexpected EOF in archive")));
432              return false;
433            }
434          set_next_block_after (blk);
435          bytes_read = safe_read (file->fd, diff_buffer, rdsize);
436          if (bytes_read < 0)
437            {
438              read_diag_details (file->stat_info->orig_file_name,
439                                 file->stat_info->sparse_map[index].offset
440                                     + file->stat_info->sparse_map[index].numbytes
441                                     - size_left,
442                                 rdsize);
443              return false;
444            }
445          file->dumped_size += bytes_read;
446          size_left -= bytes_read;
447          if (memcmp (blk->buffer, diff_buffer, rdsize))
448            {
449              report_difference (file->stat_info, _("Contents differ"));
450              return false;
451            }
452        }
453      return true;
454    }
455    
456    bool
457    sparse_diff_file (int fd, struct tar_stat_info *stat)
458    {
459      bool rc = true;
460      struct tar_sparse_file file;
461      size_t i;
462      off_t offset = 0;
463      
464      file.stat_info = stat;
465      file.fd = fd;
466    
467      if (!sparse_select_optab (&file)
468          || !tar_sparse_init (&file))
469        return dump_status_not_implemented;
470    
471      rc = tar_sparse_decode_header (&file);
472      for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
473        {
474          rc = check_sparse_region (&file,
475                                    offset, file.stat_info->sparse_map[i].offset)
476            && check_data_region (&file, i);
477          offset = file.stat_info->sparse_map[i].offset
478                    + file.stat_info->sparse_map[i].numbytes;
479        }
480    
481      if (rc)
482        skip_file (file.stat_info->archive_file_size - file.dumped_size);
483    
484      tar_sparse_done (&file);
485      return rc;
486    }
487    
488            
489  /* Old GNU Format. The sparse file information is stored in the  /* Old GNU Format. The sparse file information is stored in the
490     oldgnu_header in the following manner:     oldgnu_header in the following manner:

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26