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

Diff of /tar/src/extract.c

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

revision 1.52 by gray, Wed Oct 8 11:17:36 2003 UTC revision 1.53 by gray, Mon Nov 17 07:37:03 2003 UTC
# Line 486  maybe_recoverable (char *file_name, int Line 486  maybe_recoverable (char *file_name, int
486      }      }
487  }  }
488    
 /* Translate the sparse information on the header, and in any  
    subsequent extended headers, into an array of structures with true  
    numbers, as opposed to character strings.  Return nonzero if  
    successful.  
   
    This function invalidates current_header.  */  
   
 bool  
 fill_in_sparse_array (void)  
 {  
   off_t sparse_data_size = current_stat_info.stat.st_size;  
   off_t file_size = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);  
   int sparses;  
   int counter;  
   union block *h = current_header;  
   
   init_sparsearray ();  
   
   for (sparses = 0; sparses < SPARSES_IN_OLDGNU_HEADER; sparses++)  
     {  
       struct sparse const *s = &h->oldgnu_header.sp[sparses];  
       off_t offset;  
       size_t numbytes;  
       if (s->numbytes[0] == '\0')  
         break;  
       sparsearray[sparses].offset = offset = OFF_FROM_HEADER (s->offset);  
       sparsearray[sparses].numbytes = numbytes =  
         SIZE_FROM_HEADER (s->numbytes);  
       sparse_data_size -= numbytes;  
       if (offset < 0 || file_size < offset + numbytes || sparse_data_size < 0)  
         goto invalid_member;  
     }  
   
   if (h->oldgnu_header.isextended)  
     do  
       {  
         h = find_next_block ();  
         if (! h)  
           {  
             ERROR ((0, 0, _("Unexpected EOF in archive")));  
             return 0;  
           }  
   
         for (counter = 0; counter < SPARSES_IN_SPARSE_HEADER; counter++)  
           {  
             struct sparse const *s = &h->sparse_header.sp[counter];  
             off_t offset;  
             size_t numbytes;  
             if (s->numbytes[0] == '\0')  
               break;  
   
             if (sparses == sp_array_size)  
               {  
                 sp_array_size *= 2;  
                 sparsearray =  
                   xrealloc (sparsearray,  
                             sp_array_size * sizeof *sparsearray);  
               }  
   
             sparsearray[sparses].offset = offset =  
               OFF_FROM_HEADER (s->offset);  
             sparsearray[sparses].numbytes = numbytes =  
               SIZE_FROM_HEADER (s->numbytes);  
             sparse_data_size -= numbytes;  
             if (offset < 0 || file_size < offset + numbytes  
                 || sparse_data_size < 0)  
               goto invalid_member;  
             sparses++;  
           }  
           
         set_next_block_after (h);  
           
       } while (h->sparse_header.isextended);  
   
   return 1;  
   
  invalid_member:  
   ERROR ((0, 0, _("%s: invalid sparse archive member"),  
           current_stat_info.file_name));  
   return 0;  
 }  
   
   
 static off_t  
 extract_sparse_file (int fd, char const *name,  
                      off_t sizeleft, off_t file_size)  
 {  
   int sparse_ind = 0;  
   
   while (sizeleft != 0)  
     {  
       size_t written;  
       size_t count;  
       union block *data_block = find_next_block ();  
       if (! data_block)  
         {  
           ERROR ((0, 0, _("Unexpected EOF in archive")));  
           return sizeleft;  
         }  
       if (lseek (fd, sparsearray[sparse_ind].offset, SEEK_SET) < 0)  
         {  
           seek_error_details (name, sparsearray[sparse_ind].offset);  
           return sizeleft;  
         }  
       written = sparsearray[sparse_ind++].numbytes;  
       while (written > BLOCKSIZE)  
         {  
           count = full_write (fd, data_block->buffer, BLOCKSIZE);  
           written -= count;  
           sizeleft -= count;  
           if (count != BLOCKSIZE)  
             {  
               write_error_details (name, count, BLOCKSIZE);  
               return sizeleft;  
             }  
           set_next_block_after (data_block);  
           data_block = find_next_block ();  
           if (! data_block)  
             {  
               ERROR ((0, 0, _("Unexpected EOF in archive")));  
               return sizeleft;  
             }  
         }  
   
       count = full_write (fd, data_block->buffer, written);  
       sizeleft -= count;  
   
       if (count != written)  
         {  
           write_error_details (name, count, written);  
           return sizeleft;  
         }  
   
       set_next_block_after (data_block);  
     }  
   
   if (ftruncate (fd, file_size) != 0)  
     truncate_error (name);  
   
   return 0;  
 }  
   
489  /* Fix the statuses of all directories whose statuses need fixing, and  /* Fix the statuses of all directories whose statuses need fixing, and
490     which are not ancestors of FILE_NAME.  If AFTER_SYMLINKS is     which are not ancestors of FILE_NAME.  If AFTER_SYMLINKS is
491     nonzero, do this for all such directories; otherwise, stop at the     nonzero, do this for all such directories; otherwise, stop at the
# Line 712  extract_archive (void) Line 570  extract_archive (void)
570    /* Print the block from current_header and current_stat.  */    /* Print the block from current_header and current_stat.  */
571    
572    if (verbose_option)    if (verbose_option)
573      print_header (-1);      print_header (&current_stat_info, -1);
574    
575    file_name = safer_name_suffix (current_stat_info.file_name, 0);    file_name = safer_name_suffix (current_stat_info.file_name, 0);
576    if (strip_path_elements)    if (strip_path_elements)
# Line 746  extract_archive (void) Line 604  extract_archive (void)
604    switch (typeflag)    switch (typeflag)
605      {      {
606      case GNUTYPE_SPARSE:      case GNUTYPE_SPARSE:
       file_size = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);  
       if (! fill_in_sparse_array ())  
         return;  
607        /* Fall through.  */        /* Fall through.  */
608    
609      case AREGTYPE:      case AREGTYPE:
# Line 823  extract_archive (void) Line 678  extract_archive (void)
678      extract_file:      extract_file:
679        if (typeflag == GNUTYPE_SPARSE)        if (typeflag == GNUTYPE_SPARSE)
680          {          {
681            char *name;            sparse_extract_file (fd, &current_stat_info, &size);
           size_t name_length_bis;  
   
           /* Kludge alert.  NAME is assigned to header.name because  
              during the extraction, the space that contains the header  
              will get scribbled on, and the name will get munged, so any  
              error messages that happen to contain the filename will look  
              REAL interesting unless we do this.  */  
   
           name_length_bis = strlen (file_name) + 1;  
           name = xmalloc (name_length_bis);  
           memcpy (name, file_name, name_length_bis);  
           size = extract_sparse_file (fd, name,  
                                       current_stat_info.stat.st_size, file_size);  
           free (sparsearray);  
682          }          }
683        else        else
684          for (size = current_stat_info.stat.st_size; size > 0; )          for (size = current_stat_info.stat.st_size; size > 0; )

Legend:
Removed from v.1.52  
changed lines
  Added in v.1.53

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