(tar_sparse_init): Fix recent bugfixes: Initialize dumped_size to 0.
[debian/tar] / src / sparse.c
1 /* Functions for dealing with sparse files
2
3    Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by the
7    Free Software Foundation; either version 2, or (at your option) any later
8    version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
13    Public License for more details.
14
15    You should have received a copy of the GNU General Public License along
16    with this program; if not, write to the Free Software Foundation, Inc.,
17    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18
19 #include <system.h>
20 #include <inttostr.h>
21 #include <quotearg.h>
22 #include "common.h"
23
24 struct tar_sparse_file;
25
26 enum sparse_scan_state
27   {
28     scan_begin,
29     scan_block,
30     scan_end
31   };
32
33 struct tar_sparse_optab
34 {
35   bool (*init) (struct tar_sparse_file *);
36   bool (*done) (struct tar_sparse_file *);
37   bool (*sparse_member_p) (struct tar_sparse_file *);
38   bool (*dump_header) (struct tar_sparse_file *);
39   bool (*fixup_header) (struct tar_sparse_file *);
40   bool (*decode_header) (struct tar_sparse_file *);
41   bool (*scan_block) (struct tar_sparse_file *, enum sparse_scan_state,
42                       void *);
43   bool (*dump_region) (struct tar_sparse_file *, size_t);
44   bool (*extract_region) (struct tar_sparse_file *, size_t);
45 };
46
47 struct tar_sparse_file
48 {
49   int fd;                           /* File descriptor */
50   bool seekable;                    /* Is fd seekable? */
51   off_t offset;                     /* Current offset in fd if seekable==false.
52                                        Otherwise unused */
53   off_t dumped_size;                /* Number of bytes actually written
54                                        to the archive */
55   struct tar_stat_info *stat_info;  /* Information about the file */
56   struct tar_sparse_optab const *optab;
57   void *closure;                    /* Any additional data optab calls might
58                                        require */
59 };
60
61 /* Dump zeros to file->fd until offset is reached. It is used instead of
62    lseek if the output file is not seekable */
63 static bool
64 dump_zeros (struct tar_sparse_file *file, off_t offset)
65 {
66   static char const zero_buf[BLOCKSIZE];
67
68   if (offset < file->offset)
69     {
70       errno = EINVAL;
71       return false;
72     }
73
74   while (file->offset < offset)
75     {
76       size_t size = (BLOCKSIZE < offset - file->offset
77                      ? BLOCKSIZE
78                      : offset - file->offset);
79       ssize_t wrbytes;
80
81       wrbytes = write (file->fd, zero_buf, size);
82       if (wrbytes <= 0)
83         {
84           if (wrbytes == 0)
85             errno = EINVAL;
86           return false;
87         }
88       file->offset += wrbytes;
89     }
90
91   return true;
92 }
93
94 static bool
95 tar_sparse_member_p (struct tar_sparse_file *file)
96 {
97   if (file->optab->sparse_member_p)
98     return file->optab->sparse_member_p (file);
99   return false;
100 }
101
102 static bool
103 tar_sparse_init (struct tar_sparse_file *file)
104 {
105   file->dumped_size = 0;
106   if (file->optab->init)
107     return file->optab->init (file);
108   return true;
109 }
110
111 static bool
112 tar_sparse_done (struct tar_sparse_file *file)
113 {
114   if (file->optab->done)
115     return file->optab->done (file);
116   return true;
117 }
118
119 static bool
120 tar_sparse_scan (struct tar_sparse_file *file, enum sparse_scan_state state,
121                  void *block)
122 {
123   if (file->optab->scan_block)
124     return file->optab->scan_block (file, state, block);
125   return true;
126 }
127
128 static bool
129 tar_sparse_dump_region (struct tar_sparse_file *file, size_t i)
130 {
131   if (file->optab->dump_region)
132     return file->optab->dump_region (file, i);
133   return false;
134 }
135
136 static bool
137 tar_sparse_extract_region (struct tar_sparse_file *file, size_t i)
138 {
139   if (file->optab->extract_region)
140     return file->optab->extract_region (file, i);
141   return false;
142 }
143
144 static bool
145 tar_sparse_dump_header (struct tar_sparse_file *file)
146 {
147   if (file->optab->dump_header)
148     return file->optab->dump_header (file);
149   return false;
150 }
151
152 static bool
153 tar_sparse_decode_header (struct tar_sparse_file *file)
154 {
155   if (file->optab->decode_header)
156     return file->optab->decode_header (file);
157   return true;
158 }
159
160 static bool
161 tar_sparse_fixup_header (struct tar_sparse_file *file)
162 {
163   if (file->optab->fixup_header)
164     return file->optab->fixup_header (file);
165   return true;
166 }
167
168 \f
169 static bool
170 lseek_or_error (struct tar_sparse_file *file, off_t offset)
171 {
172   if (file->seekable
173       ? lseek (file->fd, offset, SEEK_SET) < 0
174       : ! dump_zeros (file, offset))
175     {
176       seek_diag_details (file->stat_info->orig_file_name, offset);
177       return false;
178     }
179   return true;
180 }
181
182 /* Takes a blockful of data and basically cruises through it to see if
183    it's made *entirely* of zeros, returning a 0 the instant it finds
184    something that is a nonzero, i.e., useful data.  */
185 static bool
186 zero_block_p (char const *buffer, size_t size)
187 {
188   while (size--)
189     if (*buffer++)
190       return false;
191   return true;
192 }
193
194 static void
195 sparse_add_map (struct tar_stat_info *st, struct sp_array const *sp)
196 {
197   struct sp_array *sparse_map = st->sparse_map;
198   size_t avail = st->sparse_map_avail;
199   if (avail == st->sparse_map_size)
200     st->sparse_map = sparse_map =
201       x2nrealloc (sparse_map, &st->sparse_map_size, sizeof *sparse_map);
202   sparse_map[avail] = *sp;
203   st->sparse_map_avail = avail + 1;
204 }
205
206 /* Scan the sparse file and create its map */
207 static bool
208 sparse_scan_file (struct tar_sparse_file *file)
209 {
210   struct tar_stat_info *st = file->stat_info;
211   int fd = file->fd;
212   char buffer[BLOCKSIZE];
213   size_t count;
214   off_t offset = 0;
215   struct sp_array sp = {0, 0};
216
217   if (!lseek_or_error (file, 0))
218     return false;
219
220   if (!tar_sparse_scan (file, scan_begin, NULL))
221     return false;
222
223   while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
224          && count != SAFE_READ_ERROR)
225     {
226       /* Analyze the block.  */
227       if (zero_block_p (buffer, count))
228         {
229           if (sp.numbytes)
230             {
231               sparse_add_map (st, &sp);
232               sp.numbytes = 0;
233               if (!tar_sparse_scan (file, scan_block, NULL))
234                 return false;
235             }
236         }
237       else
238         {
239           if (sp.numbytes == 0)
240             sp.offset = offset;
241           sp.numbytes += count;
242           st->archive_file_size += count;
243           if (!tar_sparse_scan (file, scan_block, buffer))
244             return false;
245         }
246
247       offset += count;
248     }
249
250   if (sp.numbytes == 0)
251     sp.offset = offset;
252
253   sparse_add_map (st, &sp);
254   st->archive_file_size += count;
255   return tar_sparse_scan (file, scan_end, NULL);
256 }
257
258 static struct tar_sparse_optab const oldgnu_optab;
259 static struct tar_sparse_optab const star_optab;
260 static struct tar_sparse_optab const pax_optab;
261
262 static bool
263 sparse_select_optab (struct tar_sparse_file *file)
264 {
265   switch (current_format == DEFAULT_FORMAT ? archive_format : current_format)
266     {
267     case V7_FORMAT:
268     case USTAR_FORMAT:
269       return false;
270
271     case OLDGNU_FORMAT:
272     case GNU_FORMAT: /*FIXME: This one should disappear? */
273       file->optab = &oldgnu_optab;
274       break;
275
276     case POSIX_FORMAT:
277       file->optab = &pax_optab;
278       break;
279
280     case STAR_FORMAT:
281       file->optab = &star_optab;
282       break;
283
284     default:
285       return false;
286     }
287   return true;
288 }
289
290 static bool
291 sparse_dump_region (struct tar_sparse_file *file, size_t i)
292 {
293   union block *blk;
294   off_t bytes_left = file->stat_info->sparse_map[i].numbytes;
295
296   if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
297     return false;
298
299   while (bytes_left > 0)
300     {
301       size_t bufsize = (bytes_left > BLOCKSIZE) ? BLOCKSIZE : bytes_left;
302       size_t bytes_read;
303
304       blk = find_next_block ();
305       bytes_read = safe_read (file->fd, blk->buffer, bufsize);
306       if (bytes_read == SAFE_READ_ERROR)
307         {
308           read_diag_details (file->stat_info->orig_file_name,
309                              (file->stat_info->sparse_map[i].offset
310                               + file->stat_info->sparse_map[i].numbytes
311                               - bytes_left),
312                              bufsize);
313           return false;
314         }
315
316       memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
317       bytes_left -= bytes_read;
318       file->dumped_size += bytes_read;
319       set_next_block_after (blk);
320     }
321
322   return true;
323 }
324
325 static bool
326 sparse_extract_region (struct tar_sparse_file *file, size_t i)
327 {
328   size_t write_size;
329
330   if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
331     return false;
332
333   write_size = file->stat_info->sparse_map[i].numbytes;
334
335   if (write_size == 0)
336     {
337       /* Last block of the file is a hole */
338       if (file->seekable && sys_truncate (file->fd))
339         truncate_warn (file->stat_info->orig_file_name);
340     }
341   else while (write_size > 0)
342     {
343       size_t count;
344       size_t wrbytes = (write_size > BLOCKSIZE) ? BLOCKSIZE : write_size;
345       union block *blk = find_next_block ();
346       if (!blk)
347         {
348           ERROR ((0, 0, _("Unexpected EOF in archive")));
349           return false;
350         }
351       set_next_block_after (blk);
352       count = full_write (file->fd, blk->buffer, wrbytes);
353       write_size -= count;
354       file->dumped_size += count;
355       file->offset += count;
356       if (count != wrbytes)
357         {
358           write_error_details (file->stat_info->orig_file_name,
359                                count, wrbytes);
360           return false;
361         }
362     }
363   return true;
364 }
365
366 \f
367
368 /* Interface functions */
369 enum dump_status
370 sparse_dump_file (int fd, struct tar_stat_info *st)
371 {
372   bool rc;
373   struct tar_sparse_file file = { 0, };
374
375   file.stat_info = st;
376   file.fd = fd;
377   file.seekable = true; /* File *must* be seekable for dump to work */
378
379   if (!sparse_select_optab (&file)
380       || !tar_sparse_init (&file))
381     return dump_status_not_implemented;
382
383   rc = sparse_scan_file (&file);
384   if (rc && file.optab->dump_region)
385     {
386       tar_sparse_dump_header (&file);
387
388       if (fd >= 0)
389         {
390           size_t i;
391
392           for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
393             rc = tar_sparse_dump_region (&file, i);
394         }
395     }
396
397   pad_archive (file.stat_info->archive_file_size - file.dumped_size);
398   return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
399 }
400
401 /* Returns true if the file represented by stat is a sparse one */
402 bool
403 sparse_file_p (struct tar_stat_info *st)
404 {
405   return (ST_NBLOCKS (st->stat)
406           < (st->stat.st_size / ST_NBLOCKSIZE
407              + (st->stat.st_size % ST_NBLOCKSIZE != 0)));
408 }
409
410 bool
411 sparse_member_p (struct tar_stat_info *st)
412 {
413   struct tar_sparse_file file;
414
415   if (!sparse_select_optab (&file))
416     return false;
417   file.stat_info = st;
418   return tar_sparse_member_p (&file);
419 }
420
421 bool
422 sparse_fixup_header (struct tar_stat_info *st)
423 {
424   struct tar_sparse_file file;
425
426   if (!sparse_select_optab (&file))
427     return false;
428   file.stat_info = st;
429   return tar_sparse_fixup_header (&file);
430 }
431
432 enum dump_status
433 sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
434 {
435   bool rc = true;
436   struct tar_sparse_file file;
437   size_t i;
438
439   file.stat_info = st;
440   file.fd = fd;
441   file.seekable = lseek (fd, 0, SEEK_SET) == 0;
442   file.offset = 0;
443
444   if (!sparse_select_optab (&file)
445       || !tar_sparse_init (&file))
446     return dump_status_not_implemented;
447
448   rc = tar_sparse_decode_header (&file);
449   for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
450     rc = tar_sparse_extract_region (&file, i);
451   *size = file.stat_info->archive_file_size - file.dumped_size;
452   return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
453 }
454
455 enum dump_status
456 sparse_skip_file (struct tar_stat_info *st)
457 {
458   bool rc = true;
459   struct tar_sparse_file file;
460
461   file.stat_info = st;
462   file.fd = -1;
463
464   if (!sparse_select_optab (&file)
465       || !tar_sparse_init (&file))
466     return dump_status_not_implemented;
467
468   rc = tar_sparse_decode_header (&file);
469   skip_file (file.stat_info->archive_file_size);
470   return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
471 }
472
473 \f
474 static bool
475 check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
476 {
477   if (!lseek_or_error (file, beg))
478     return false;
479
480   while (beg < end)
481     {
482       size_t bytes_read;
483       size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;
484       char diff_buffer[BLOCKSIZE];
485
486       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
487       if (bytes_read == SAFE_READ_ERROR)
488         {
489           read_diag_details (file->stat_info->orig_file_name,
490                              beg,
491                              rdsize);
492           return false;
493         }
494       if (!zero_block_p (diff_buffer, bytes_read))
495         {
496           char begbuf[INT_BUFSIZE_BOUND (off_t)];
497           report_difference (file->stat_info,
498                              _("File fragment at %s is not a hole"),
499                              offtostr (beg, begbuf));
500           return false;
501         }
502
503       beg += bytes_read;
504     }
505   return true;
506 }
507
508 static bool
509 check_data_region (struct tar_sparse_file *file, size_t i)
510 {
511   size_t size_left;
512
513   if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
514     return false;
515   size_left = file->stat_info->sparse_map[i].numbytes;
516   while (size_left > 0)
517     {
518       size_t bytes_read;
519       size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
520       char diff_buffer[BLOCKSIZE];
521
522       union block *blk = find_next_block ();
523       if (!blk)
524         {
525           ERROR ((0, 0, _("Unexpected EOF in archive")));
526           return false;
527         }
528       set_next_block_after (blk);
529       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
530       if (bytes_read == SAFE_READ_ERROR)
531         {
532           read_diag_details (file->stat_info->orig_file_name,
533                              (file->stat_info->sparse_map[i].offset
534                               + file->stat_info->sparse_map[i].numbytes
535                               - size_left),
536                              rdsize);
537           return false;
538         }
539       file->dumped_size += bytes_read;
540       size_left -= bytes_read;
541       if (memcmp (blk->buffer, diff_buffer, rdsize))
542         {
543           report_difference (file->stat_info, _("Contents differ"));
544           return false;
545         }
546     }
547   return true;
548 }
549
550 bool
551 sparse_diff_file (int fd, struct tar_stat_info *st)
552 {
553   bool rc = true;
554   struct tar_sparse_file file;
555   size_t i;
556   off_t offset = 0;
557
558   file.stat_info = st;
559   file.fd = fd;
560
561   if (!sparse_select_optab (&file)
562       || !tar_sparse_init (&file))
563     return dump_status_not_implemented;
564
565   rc = tar_sparse_decode_header (&file);
566   for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
567     {
568       rc = check_sparse_region (&file,
569                                 offset, file.stat_info->sparse_map[i].offset)
570         && check_data_region (&file, i);
571       offset = file.stat_info->sparse_map[i].offset
572                 + file.stat_info->sparse_map[i].numbytes;
573     }
574
575   if (!rc)
576     skip_file (file.stat_info->archive_file_size - file.dumped_size);
577
578   tar_sparse_done (&file);
579   return rc;
580 }
581
582 \f
583 /* Old GNU Format. The sparse file information is stored in the
584    oldgnu_header in the following manner:
585
586    The header is marked with type 'S'. Its `size' field contains
587    the cumulative size of all non-empty blocks of the file. The
588    actual file size is stored in `realsize' member of oldgnu_header.
589
590    The map of the file is stored in a list of `struct sparse'.
591    Each struct contains offset to the block of data and its
592    size (both as octal numbers). The first file header contains
593    at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map
594    contains more structs, then the field `isextended' of the main
595    header is set to 1 (binary) and the `struct sparse_header'
596    header follows, containing at most 21 following structs
597    (SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'
598    field of the extended header is set and next  next extension header
599    follows, etc... */
600
601 enum oldgnu_add_status
602   {
603     add_ok,
604     add_finish,
605     add_fail
606   };
607
608 static bool
609 oldgnu_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
610 {
611   return current_header->header.typeflag == GNUTYPE_SPARSE;
612 }
613
614 /* Add a sparse item to the sparse file and its obstack */
615 static enum oldgnu_add_status
616 oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
617 {
618   struct sp_array sp;
619
620   if (s->numbytes[0] == '\0')
621     return add_finish;
622   sp.offset = OFF_FROM_HEADER (s->offset);
623   sp.numbytes = SIZE_FROM_HEADER (s->numbytes);
624   if (sp.offset < 0
625       || file->stat_info->stat.st_size < sp.offset + sp.numbytes
626       || file->stat_info->archive_file_size < 0)
627     return add_fail;
628
629   sparse_add_map (file->stat_info, &sp);
630   return add_ok;
631 }
632
633 static bool
634 oldgnu_fixup_header (struct tar_sparse_file *file)
635 {
636   /* NOTE! st_size was initialized from the header
637      which actually contains archived size. The following fixes it */
638   file->stat_info->archive_file_size = file->stat_info->stat.st_size;
639   file->stat_info->stat.st_size =
640     OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
641   return true;
642 }
643
644 /* Convert old GNU format sparse data to internal representation */
645 static bool
646 oldgnu_get_sparse_info (struct tar_sparse_file *file)
647 {
648   size_t i;
649   union block *h = current_header;
650   int ext_p;
651   enum oldgnu_add_status rc;
652
653   file->stat_info->sparse_map_avail = 0;
654   for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
655     {
656       rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
657       if (rc != add_ok)
658         break;
659     }
660
661   for (ext_p = h->oldgnu_header.isextended;
662        rc == add_ok && ext_p; ext_p = h->sparse_header.isextended)
663     {
664       h = find_next_block ();
665       if (!h)
666         {
667           ERROR ((0, 0, _("Unexpected EOF in archive")));
668           return false;
669         }
670       set_next_block_after (h);
671       for (i = 0; i < SPARSES_IN_SPARSE_HEADER && rc == add_ok; i++)
672         rc = oldgnu_add_sparse (file, &h->sparse_header.sp[i]);
673     }
674
675   if (rc == add_fail)
676     {
677       ERROR ((0, 0, _("%s: invalid sparse archive member"),
678               file->stat_info->orig_file_name));
679       return false;
680     }
681   return true;
682 }
683
684 static void
685 oldgnu_store_sparse_info (struct tar_sparse_file *file, size_t *pindex,
686                           struct sparse *sp, size_t sparse_size)
687 {
688   for (; *pindex < file->stat_info->sparse_map_avail
689          && sparse_size > 0; sparse_size--, sp++, ++*pindex)
690     {
691       OFF_TO_CHARS (file->stat_info->sparse_map[*pindex].offset,
692                     sp->offset);
693       SIZE_TO_CHARS (file->stat_info->sparse_map[*pindex].numbytes,
694                      sp->numbytes);
695     }
696 }
697
698 static bool
699 oldgnu_dump_header (struct tar_sparse_file *file)
700 {
701   off_t block_ordinal = current_block_ordinal ();
702   union block *blk;
703   size_t i;
704
705   blk = start_header (file->stat_info);
706   blk->header.typeflag = GNUTYPE_SPARSE;
707   if (file->stat_info->sparse_map_avail > SPARSES_IN_OLDGNU_HEADER)
708     blk->oldgnu_header.isextended = 1;
709
710   /* Store the real file size */
711   OFF_TO_CHARS (file->stat_info->stat.st_size, blk->oldgnu_header.realsize);
712   /* Store the effective (shrunken) file size */
713   OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
714
715   i = 0;
716   oldgnu_store_sparse_info (file, &i,
717                             blk->oldgnu_header.sp,
718                             SPARSES_IN_OLDGNU_HEADER);
719   blk->oldgnu_header.isextended = i < file->stat_info->sparse_map_avail;
720   finish_header (file->stat_info, blk, block_ordinal);
721
722   while (i < file->stat_info->sparse_map_avail)
723     {
724       blk = find_next_block ();
725       memset (blk->buffer, 0, BLOCKSIZE);
726       oldgnu_store_sparse_info (file, &i,
727                                 blk->sparse_header.sp,
728                                 SPARSES_IN_SPARSE_HEADER);
729       set_next_block_after (blk);
730       if (i < file->stat_info->sparse_map_avail)
731         blk->sparse_header.isextended = 1;
732       else
733         break;
734     }
735   return true;
736 }
737
738 static struct tar_sparse_optab const oldgnu_optab = {
739   NULL,  /* No init function */
740   NULL,  /* No done function */
741   oldgnu_sparse_member_p,
742   oldgnu_dump_header,
743   oldgnu_fixup_header,
744   oldgnu_get_sparse_info,
745   NULL,  /* No scan_block function */
746   sparse_dump_region,
747   sparse_extract_region,
748 };
749
750 \f
751 /* Star */
752
753 static bool
754 star_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
755 {
756   return current_header->header.typeflag == GNUTYPE_SPARSE;
757 }
758
759 static bool
760 star_fixup_header (struct tar_sparse_file *file)
761 {
762   /* NOTE! st_size was initialized from the header
763      which actually contains archived size. The following fixes it */
764   file->stat_info->archive_file_size = file->stat_info->stat.st_size;
765   file->stat_info->stat.st_size =
766             OFF_FROM_HEADER (current_header->star_in_header.realsize);
767   return true;
768 }
769
770 /* Convert STAR format sparse data to internal representation */
771 static bool
772 star_get_sparse_info (struct tar_sparse_file *file)
773 {
774   size_t i;
775   union block *h = current_header;
776   int ext_p;
777   enum oldgnu_add_status rc = add_ok;
778
779   file->stat_info->sparse_map_avail = 0;
780
781   if (h->star_in_header.prefix[0] == '\0'
782       && h->star_in_header.sp[0].offset[10] != '\0')
783     {
784       /* Old star format */
785       for (i = 0; i < SPARSES_IN_STAR_HEADER; i++)
786         {
787           rc = oldgnu_add_sparse (file, &h->star_in_header.sp[i]);
788           if (rc != add_ok)
789             break;
790         }
791       ext_p = h->star_in_header.isextended;
792     }
793   else
794     ext_p = 1;
795
796   for (; rc == add_ok && ext_p; ext_p = h->star_ext_header.isextended)
797     {
798       h = find_next_block ();
799       if (!h)
800         {
801           ERROR ((0, 0, _("Unexpected EOF in archive")));
802           return false;
803         }
804       set_next_block_after (h);
805       for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++)
806         rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]);
807     }
808
809   if (rc == add_fail)
810     {
811       ERROR ((0, 0, _("%s: invalid sparse archive member"),
812               file->stat_info->orig_file_name));
813       return false;
814     }
815   return true;
816 }
817
818
819 static struct tar_sparse_optab const star_optab = {
820   NULL,  /* No init function */
821   NULL,  /* No done function */
822   star_sparse_member_p,
823   NULL,
824   star_fixup_header,
825   star_get_sparse_info,
826   NULL,  /* No scan_block function */
827   NULL, /* No dump region function */
828   sparse_extract_region,
829 };
830
831 \f
832 /* GNU PAX sparse file format. The sparse file map is stored in
833    x header:
834
835    GNU.sparse.size      Real size of the stored file
836    GNU.sparse.numblocks Number of blocks in the sparse map
837    repeat numblocks time
838      GNU.sparse.offset    Offset of the next data block
839      GNU.sparse.numbytes  Size of the next data block
840    end repeat
841 */
842
843 static bool
844 pax_sparse_member_p (struct tar_sparse_file *file)
845 {
846   return file->stat_info->archive_file_size != file->stat_info->stat.st_size;
847 }
848
849 static bool
850 pax_dump_header (struct tar_sparse_file *file)
851 {
852   off_t block_ordinal = current_block_ordinal ();
853   union block *blk;
854   size_t i;
855
856   /* Store the real file size */
857   xheader_store ("GNU.sparse.size", file->stat_info, NULL);
858   xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
859   for (i = 0; i < file->stat_info->sparse_map_avail; i++)
860     {
861       xheader_store ("GNU.sparse.offset", file->stat_info, &i);
862       xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
863     }
864
865   blk = start_header (file->stat_info);
866   /* Store the effective (shrunken) file size */
867   OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
868   finish_header (file->stat_info, blk, block_ordinal);
869   return true;
870 }
871
872 static struct tar_sparse_optab const pax_optab = {
873   NULL,  /* No init function */
874   NULL,  /* No done function */
875   pax_sparse_member_p,
876   pax_dump_header,
877   NULL,  /* No decode_header function */
878   NULL,  /* No fixup_header function */
879   NULL,  /* No scan_block function */
880   sparse_dump_region,
881   sparse_extract_region,
882 };