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