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