1 /* Functions for dealing with sparse files
3 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Free Software
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any later
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 struct tar_sparse_file
;
26 static bool sparse_select_optab (struct tar_sparse_file
*file
);
28 enum sparse_scan_state
35 struct tar_sparse_optab
37 bool (*init
) (struct tar_sparse_file
*);
38 bool (*done
) (struct tar_sparse_file
*);
39 bool (*sparse_member_p
) (struct tar_sparse_file
*);
40 bool (*dump_header
) (struct tar_sparse_file
*);
41 bool (*fixup_header
) (struct tar_sparse_file
*);
42 bool (*decode_header
) (struct tar_sparse_file
*);
43 bool (*scan_block
) (struct tar_sparse_file
*, enum sparse_scan_state
,
45 bool (*dump_region
) (struct tar_sparse_file
*, size_t);
46 bool (*extract_region
) (struct tar_sparse_file
*, size_t);
49 struct tar_sparse_file
51 int fd
; /* File descriptor */
52 bool seekable
; /* Is fd seekable? */
53 off_t offset
; /* Current offset in fd if seekable==false.
55 off_t dumped_size
; /* Number of bytes actually written
57 struct tar_stat_info
*stat_info
; /* Information about the file */
58 struct tar_sparse_optab
const *optab
; /* Operation table */
59 void *closure
; /* Any additional data optab calls might
63 /* Dump zeros to file->fd until offset is reached. It is used instead of
64 lseek if the output file is not seekable */
66 dump_zeros (struct tar_sparse_file
*file
, off_t offset
)
68 static char const zero_buf
[BLOCKSIZE
];
70 if (offset
< file
->offset
)
76 while (file
->offset
< offset
)
78 size_t size
= (BLOCKSIZE
< offset
- file
->offset
80 : offset
- file
->offset
);
83 wrbytes
= write (file
->fd
, zero_buf
, size
);
90 file
->offset
+= wrbytes
;
97 tar_sparse_member_p (struct tar_sparse_file
*file
)
99 if (file
->optab
->sparse_member_p
)
100 return file
->optab
->sparse_member_p (file
);
105 tar_sparse_init (struct tar_sparse_file
*file
)
107 memset (file
, 0, sizeof *file
);
109 if (!sparse_select_optab (file
))
112 if (file
->optab
->init
)
113 return file
->optab
->init (file
);
119 tar_sparse_done (struct tar_sparse_file
*file
)
121 if (file
->optab
->done
)
122 return file
->optab
->done (file
);
127 tar_sparse_scan (struct tar_sparse_file
*file
, enum sparse_scan_state state
,
130 if (file
->optab
->scan_block
)
131 return file
->optab
->scan_block (file
, state
, block
);
136 tar_sparse_dump_region (struct tar_sparse_file
*file
, size_t i
)
138 if (file
->optab
->dump_region
)
139 return file
->optab
->dump_region (file
, i
);
144 tar_sparse_extract_region (struct tar_sparse_file
*file
, size_t i
)
146 if (file
->optab
->extract_region
)
147 return file
->optab
->extract_region (file
, i
);
152 tar_sparse_dump_header (struct tar_sparse_file
*file
)
154 if (file
->optab
->dump_header
)
155 return file
->optab
->dump_header (file
);
160 tar_sparse_decode_header (struct tar_sparse_file
*file
)
162 if (file
->optab
->decode_header
)
163 return file
->optab
->decode_header (file
);
168 tar_sparse_fixup_header (struct tar_sparse_file
*file
)
170 if (file
->optab
->fixup_header
)
171 return file
->optab
->fixup_header (file
);
177 lseek_or_error (struct tar_sparse_file
*file
, off_t offset
)
180 ? lseek (file
->fd
, offset
, SEEK_SET
) < 0
181 : ! dump_zeros (file
, offset
))
183 seek_diag_details (file
->stat_info
->orig_file_name
, offset
);
189 /* Takes a blockful of data and basically cruises through it to see if
190 it's made *entirely* of zeros, returning a 0 the instant it finds
191 something that is a nonzero, i.e., useful data. */
193 zero_block_p (char const *buffer
, size_t size
)
202 sparse_add_map (struct tar_stat_info
*st
, struct sp_array
const *sp
)
204 struct sp_array
*sparse_map
= st
->sparse_map
;
205 size_t avail
= st
->sparse_map_avail
;
206 if (avail
== st
->sparse_map_size
)
207 st
->sparse_map
= sparse_map
=
208 x2nrealloc (sparse_map
, &st
->sparse_map_size
, sizeof *sparse_map
);
209 sparse_map
[avail
] = *sp
;
210 st
->sparse_map_avail
= avail
+ 1;
213 /* Scan the sparse file and create its map */
215 sparse_scan_file (struct tar_sparse_file
*file
)
217 struct tar_stat_info
*st
= file
->stat_info
;
219 char buffer
[BLOCKSIZE
];
222 struct sp_array sp
= {0, 0};
224 if (!lseek_or_error (file
, 0))
227 st
->archive_file_size
= 0;
229 if (!tar_sparse_scan (file
, scan_begin
, NULL
))
232 while ((count
= safe_read (fd
, buffer
, sizeof buffer
)) != 0
233 && count
!= SAFE_READ_ERROR
)
235 /* Analyze the block. */
236 if (zero_block_p (buffer
, count
))
240 sparse_add_map (st
, &sp
);
242 if (!tar_sparse_scan (file
, scan_block
, NULL
))
248 if (sp
.numbytes
== 0)
250 sp
.numbytes
+= count
;
251 st
->archive_file_size
+= count
;
252 if (!tar_sparse_scan (file
, scan_block
, buffer
))
259 if (sp
.numbytes
== 0)
262 sparse_add_map (st
, &sp
);
263 st
->archive_file_size
+= count
;
264 return tar_sparse_scan (file
, scan_end
, NULL
);
267 static struct tar_sparse_optab
const oldgnu_optab
;
268 static struct tar_sparse_optab
const star_optab
;
269 static struct tar_sparse_optab
const pax_optab
;
272 sparse_select_optab (struct tar_sparse_file
*file
)
274 switch (current_format
== DEFAULT_FORMAT
? archive_format
: current_format
)
281 case GNU_FORMAT
: /*FIXME: This one should disappear? */
282 file
->optab
= &oldgnu_optab
;
286 file
->optab
= &pax_optab
;
290 file
->optab
= &star_optab
;
300 sparse_dump_region (struct tar_sparse_file
*file
, size_t i
)
303 off_t bytes_left
= file
->stat_info
->sparse_map
[i
].numbytes
;
305 if (!lseek_or_error (file
, file
->stat_info
->sparse_map
[i
].offset
))
308 while (bytes_left
> 0)
310 size_t bufsize
= (bytes_left
> BLOCKSIZE
) ? BLOCKSIZE
: bytes_left
;
313 blk
= find_next_block ();
314 bytes_read
= safe_read (file
->fd
, blk
->buffer
, bufsize
);
315 if (bytes_read
== SAFE_READ_ERROR
)
317 read_diag_details (file
->stat_info
->orig_file_name
,
318 (file
->stat_info
->sparse_map
[i
].offset
319 + file
->stat_info
->sparse_map
[i
].numbytes
325 memset (blk
->buffer
+ bytes_read
, 0, BLOCKSIZE
- bytes_read
);
326 bytes_left
-= bytes_read
;
327 file
->dumped_size
+= bytes_read
;
328 set_next_block_after (blk
);
335 sparse_extract_region (struct tar_sparse_file
*file
, size_t i
)
339 if (!lseek_or_error (file
, file
->stat_info
->sparse_map
[i
].offset
))
342 write_size
= file
->stat_info
->sparse_map
[i
].numbytes
;
346 /* Last block of the file is a hole */
347 if (file
->seekable
&& sys_truncate (file
->fd
))
348 truncate_warn (file
->stat_info
->orig_file_name
);
350 else while (write_size
> 0)
353 size_t wrbytes
= (write_size
> BLOCKSIZE
) ? BLOCKSIZE
: write_size
;
354 union block
*blk
= find_next_block ();
357 ERROR ((0, 0, _("Unexpected EOF in archive")));
360 set_next_block_after (blk
);
361 count
= full_write (file
->fd
, blk
->buffer
, wrbytes
);
363 file
->dumped_size
+= count
;
364 mv_size_left (file
->stat_info
->archive_file_size
- file
->dumped_size
);
365 file
->offset
+= count
;
366 if (count
!= wrbytes
)
368 write_error_details (file
->stat_info
->orig_file_name
,
378 /* Interface functions */
380 sparse_dump_file (int fd
, struct tar_stat_info
*st
)
383 struct tar_sparse_file file
;
385 if (!tar_sparse_init (&file
))
386 return dump_status_not_implemented
;
390 file
.seekable
= true; /* File *must* be seekable for dump to work */
392 rc
= sparse_scan_file (&file
);
393 if (rc
&& file
.optab
->dump_region
)
395 tar_sparse_dump_header (&file
);
401 mv_begin_write (file
.stat_info
->file_name
,
402 file
.stat_info
->stat
.st_size
,
403 file
.stat_info
->archive_file_size
- file
.dumped_size
);
404 for (i
= 0; rc
&& i
< file
.stat_info
->sparse_map_avail
; i
++)
405 rc
= tar_sparse_dump_region (&file
, i
);
409 pad_archive (file
.stat_info
->archive_file_size
- file
.dumped_size
);
410 return (tar_sparse_done (&file
) && rc
) ? dump_status_ok
: dump_status_short
;
414 sparse_member_p (struct tar_stat_info
*st
)
416 struct tar_sparse_file file
;
418 if (!tar_sparse_init (&file
))
421 return tar_sparse_member_p (&file
);
425 sparse_fixup_header (struct tar_stat_info
*st
)
427 struct tar_sparse_file file
;
429 if (!tar_sparse_init (&file
))
432 return tar_sparse_fixup_header (&file
);
436 sparse_extract_file (int fd
, struct tar_stat_info
*st
, off_t
*size
)
439 struct tar_sparse_file file
;
442 if (!tar_sparse_init (&file
))
443 return dump_status_not_implemented
;
447 file
.seekable
= lseek (fd
, 0, SEEK_SET
) == 0;
450 rc
= tar_sparse_decode_header (&file
);
451 for (i
= 0; rc
&& i
< file
.stat_info
->sparse_map_avail
; i
++)
452 rc
= tar_sparse_extract_region (&file
, i
);
453 *size
= file
.stat_info
->archive_file_size
- file
.dumped_size
;
454 return (tar_sparse_done (&file
) && rc
) ? dump_status_ok
: dump_status_short
;
458 sparse_skip_file (struct tar_stat_info
*st
)
461 struct tar_sparse_file file
;
463 if (!tar_sparse_init (&file
))
464 return dump_status_not_implemented
;
469 rc
= tar_sparse_decode_header (&file
);
470 skip_file (file
.stat_info
->archive_file_size
- file
.dumped_size
);
471 return (tar_sparse_done (&file
) && rc
) ? dump_status_ok
: dump_status_short
;
476 check_sparse_region (struct tar_sparse_file
*file
, off_t beg
, off_t end
)
478 if (!lseek_or_error (file
, beg
))
484 size_t rdsize
= BLOCKSIZE
< end
- beg
? BLOCKSIZE
: end
- beg
;
485 char diff_buffer
[BLOCKSIZE
];
487 bytes_read
= safe_read (file
->fd
, diff_buffer
, rdsize
);
488 if (bytes_read
== SAFE_READ_ERROR
)
490 read_diag_details (file
->stat_info
->orig_file_name
,
495 if (!zero_block_p (diff_buffer
, bytes_read
))
497 char begbuf
[INT_BUFSIZE_BOUND (off_t
)];
498 report_difference (file
->stat_info
,
499 _("File fragment at %s is not a hole"),
500 offtostr (beg
, begbuf
));
510 check_data_region (struct tar_sparse_file
*file
, size_t i
)
514 if (!lseek_or_error (file
, file
->stat_info
->sparse_map
[i
].offset
))
516 size_left
= file
->stat_info
->sparse_map
[i
].numbytes
;
517 mv_size_left (file
->stat_info
->archive_file_size
- file
->dumped_size
);
519 while (size_left
> 0)
522 size_t rdsize
= (size_left
> BLOCKSIZE
) ? BLOCKSIZE
: size_left
;
523 char diff_buffer
[BLOCKSIZE
];
525 union block
*blk
= find_next_block ();
528 ERROR ((0, 0, _("Unexpected EOF in archive")));
531 set_next_block_after (blk
);
532 bytes_read
= safe_read (file
->fd
, diff_buffer
, rdsize
);
533 if (bytes_read
== SAFE_READ_ERROR
)
535 read_diag_details (file
->stat_info
->orig_file_name
,
536 (file
->stat_info
->sparse_map
[i
].offset
537 + file
->stat_info
->sparse_map
[i
].numbytes
542 file
->dumped_size
+= bytes_read
;
543 size_left
-= bytes_read
;
544 mv_size_left (file
->stat_info
->archive_file_size
- file
->dumped_size
);
545 if (memcmp (blk
->buffer
, diff_buffer
, rdsize
))
547 report_difference (file
->stat_info
, _("Contents differ"));
555 sparse_diff_file (int fd
, struct tar_stat_info
*st
)
558 struct tar_sparse_file file
;
562 if (!tar_sparse_init (&file
))
563 return dump_status_not_implemented
;
567 file
.seekable
= true; /* File *must* be seekable for compare to work */
569 rc
= tar_sparse_decode_header (&file
);
571 for (i
= 0; rc
&& i
< file
.stat_info
->sparse_map_avail
; i
++)
573 rc
= check_sparse_region (&file
,
574 offset
, file
.stat_info
->sparse_map
[i
].offset
)
575 && check_data_region (&file
, i
);
576 offset
= file
.stat_info
->sparse_map
[i
].offset
577 + file
.stat_info
->sparse_map
[i
].numbytes
;
581 skip_file (file
.stat_info
->archive_file_size
- file
.dumped_size
);
584 tar_sparse_done (&file
);
589 /* Old GNU Format. The sparse file information is stored in the
590 oldgnu_header in the following manner:
592 The header is marked with type 'S'. Its `size' field contains
593 the cumulative size of all non-empty blocks of the file. The
594 actual file size is stored in `realsize' member of oldgnu_header.
596 The map of the file is stored in a list of `struct sparse'.
597 Each struct contains offset to the block of data and its
598 size (both as octal numbers). The first file header contains
599 at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map
600 contains more structs, then the field `isextended' of the main
601 header is set to 1 (binary) and the `struct sparse_header'
602 header follows, containing at most 21 following structs
603 (SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'
604 field of the extended header is set and next next extension header
607 enum oldgnu_add_status
615 oldgnu_sparse_member_p (struct tar_sparse_file
*file
__attribute__ ((unused
)))
617 return current_header
->header
.typeflag
== GNUTYPE_SPARSE
;
620 /* Add a sparse item to the sparse file and its obstack */
621 static enum oldgnu_add_status
622 oldgnu_add_sparse (struct tar_sparse_file
*file
, struct sparse
*s
)
626 if (s
->numbytes
[0] == '\0')
628 sp
.offset
= OFF_FROM_HEADER (s
->offset
);
629 sp
.numbytes
= OFF_FROM_HEADER (s
->numbytes
);
631 || sp
.offset
+ sp
.numbytes
< 0
632 || file
->stat_info
->stat
.st_size
< sp
.offset
+ sp
.numbytes
633 || file
->stat_info
->archive_file_size
< 0)
636 sparse_add_map (file
->stat_info
, &sp
);
641 oldgnu_fixup_header (struct tar_sparse_file
*file
)
643 /* NOTE! st_size was initialized from the header
644 which actually contains archived size. The following fixes it */
645 file
->stat_info
->archive_file_size
= file
->stat_info
->stat
.st_size
;
646 file
->stat_info
->stat
.st_size
=
647 OFF_FROM_HEADER (current_header
->oldgnu_header
.realsize
);
651 /* Convert old GNU format sparse data to internal representation */
653 oldgnu_get_sparse_info (struct tar_sparse_file
*file
)
656 union block
*h
= current_header
;
658 enum oldgnu_add_status rc
;
660 file
->stat_info
->sparse_map_avail
= 0;
661 for (i
= 0; i
< SPARSES_IN_OLDGNU_HEADER
; i
++)
663 rc
= oldgnu_add_sparse (file
, &h
->oldgnu_header
.sp
[i
]);
668 for (ext_p
= h
->oldgnu_header
.isextended
;
669 rc
== add_ok
&& ext_p
; ext_p
= h
->sparse_header
.isextended
)
671 h
= find_next_block ();
674 ERROR ((0, 0, _("Unexpected EOF in archive")));
677 set_next_block_after (h
);
678 for (i
= 0; i
< SPARSES_IN_SPARSE_HEADER
&& rc
== add_ok
; i
++)
679 rc
= oldgnu_add_sparse (file
, &h
->sparse_header
.sp
[i
]);
684 ERROR ((0, 0, _("%s: invalid sparse archive member"),
685 file
->stat_info
->orig_file_name
));
692 oldgnu_store_sparse_info (struct tar_sparse_file
*file
, size_t *pindex
,
693 struct sparse
*sp
, size_t sparse_size
)
695 for (; *pindex
< file
->stat_info
->sparse_map_avail
696 && sparse_size
> 0; sparse_size
--, sp
++, ++*pindex
)
698 OFF_TO_CHARS (file
->stat_info
->sparse_map
[*pindex
].offset
,
700 OFF_TO_CHARS (file
->stat_info
->sparse_map
[*pindex
].numbytes
,
706 oldgnu_dump_header (struct tar_sparse_file
*file
)
708 off_t block_ordinal
= current_block_ordinal ();
712 blk
= start_header (file
->stat_info
);
713 blk
->header
.typeflag
= GNUTYPE_SPARSE
;
714 if (file
->stat_info
->sparse_map_avail
> SPARSES_IN_OLDGNU_HEADER
)
715 blk
->oldgnu_header
.isextended
= 1;
717 /* Store the real file size */
718 OFF_TO_CHARS (file
->stat_info
->stat
.st_size
, blk
->oldgnu_header
.realsize
);
719 /* Store the effective (shrunken) file size */
720 OFF_TO_CHARS (file
->stat_info
->archive_file_size
, blk
->header
.size
);
723 oldgnu_store_sparse_info (file
, &i
,
724 blk
->oldgnu_header
.sp
,
725 SPARSES_IN_OLDGNU_HEADER
);
726 blk
->oldgnu_header
.isextended
= i
< file
->stat_info
->sparse_map_avail
;
727 finish_header (file
->stat_info
, blk
, block_ordinal
);
729 while (i
< file
->stat_info
->sparse_map_avail
)
731 blk
= find_next_block ();
732 memset (blk
->buffer
, 0, BLOCKSIZE
);
733 oldgnu_store_sparse_info (file
, &i
,
734 blk
->sparse_header
.sp
,
735 SPARSES_IN_SPARSE_HEADER
);
736 if (i
< file
->stat_info
->sparse_map_avail
)
737 blk
->sparse_header
.isextended
= 1;
738 set_next_block_after (blk
);
743 static struct tar_sparse_optab
const oldgnu_optab
= {
744 NULL
, /* No init function */
745 NULL
, /* No done function */
746 oldgnu_sparse_member_p
,
749 oldgnu_get_sparse_info
,
750 NULL
, /* No scan_block function */
752 sparse_extract_region
,
759 star_sparse_member_p (struct tar_sparse_file
*file
__attribute__ ((unused
)))
761 return current_header
->header
.typeflag
== GNUTYPE_SPARSE
;
765 star_fixup_header (struct tar_sparse_file
*file
)
767 /* NOTE! st_size was initialized from the header
768 which actually contains archived size. The following fixes it */
769 file
->stat_info
->archive_file_size
= file
->stat_info
->stat
.st_size
;
770 file
->stat_info
->stat
.st_size
=
771 OFF_FROM_HEADER (current_header
->star_in_header
.realsize
);
775 /* Convert STAR format sparse data to internal representation */
777 star_get_sparse_info (struct tar_sparse_file
*file
)
780 union block
*h
= current_header
;
782 enum oldgnu_add_status rc
= add_ok
;
784 file
->stat_info
->sparse_map_avail
= 0;
786 if (h
->star_in_header
.prefix
[0] == '\0'
787 && h
->star_in_header
.sp
[0].offset
[10] != '\0')
789 /* Old star format */
790 for (i
= 0; i
< SPARSES_IN_STAR_HEADER
; i
++)
792 rc
= oldgnu_add_sparse (file
, &h
->star_in_header
.sp
[i
]);
796 ext_p
= h
->star_in_header
.isextended
;
801 for (; rc
== add_ok
&& ext_p
; ext_p
= h
->star_ext_header
.isextended
)
803 h
= find_next_block ();
806 ERROR ((0, 0, _("Unexpected EOF in archive")));
809 set_next_block_after (h
);
810 for (i
= 0; i
< SPARSES_IN_STAR_EXT_HEADER
&& rc
== add_ok
; i
++)
811 rc
= oldgnu_add_sparse (file
, &h
->star_ext_header
.sp
[i
]);
816 ERROR ((0, 0, _("%s: invalid sparse archive member"),
817 file
->stat_info
->orig_file_name
));
824 static struct tar_sparse_optab
const star_optab
= {
825 NULL
, /* No init function */
826 NULL
, /* No done function */
827 star_sparse_member_p
,
830 star_get_sparse_info
,
831 NULL
, /* No scan_block function */
832 NULL
, /* No dump region function */
833 sparse_extract_region
,
837 /* GNU PAX sparse file format. There are several versions:
841 The initial version of sparse format used by tar 1.14-1.15.1.
842 The sparse file map is stored in x header:
844 GNU.sparse.size Real size of the stored file
845 GNU.sparse.numblocks Number of blocks in the sparse map
846 repeat numblocks time
847 GNU.sparse.offset Offset of the next data block
848 GNU.sparse.numbytes Size of the next data block
851 This has been reported as conflicting with the POSIX specs. The reason is
852 that offsets and sizes of non-zero data blocks were stored in multiple
853 instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
854 POSIX requires the latest occurrence of the variable to override all
855 previous occurrences.
857 To avoid this incompatibility two following versions were introduced.
861 Used by tar 1.15.2 -- 1.15.91 (alpha releases).
863 The sparse file map is stored in
866 GNU.sparse.size Real size of the stored file
867 GNU.sparse.numblocks Number of blocks in the sparse map
868 GNU.sparse.map Map of non-null data chunks. A string consisting
869 of comma-separated values "offset,size[,offset,size]..."
871 The resulting GNU.sparse.map string can be *very* long. While POSIX does not
872 impose any limit on the length of a x header variable, this can confuse some
877 Starting from this version, the exact sparse format version is specified
878 explicitely in the header using the following variables:
880 GNU.sparse.major Major version
881 GNU.sparse.minor Minor version
883 X header keeps the following variables:
885 GNU.sparse.name Real file name of the sparse file
886 GNU.sparse.realsize Real size of the stored file (corresponds to the old
887 GNU.sparse.size variable)
889 The name field of the ustar header is constructed using the pattern
890 "%d/GNUSparseFile.%p/%f".
892 The sparse map itself is stored in the file data block, preceding the actual
893 file data. It consists of a series of octal numbers of arbitrary length,
894 delimited by newlines. The map is padded with nulls to the nearest block
897 The first number gives the number of entries in the map. Following are map
898 entries, each one consisting of two numbers giving the offset and size of
899 the data block it describes.
901 The format is designed in such a way that non-posix aware tars and tars not
902 supporting GNU.sparse.* keywords will extract each sparse file in its
903 condensed form with the file map attached and will place it into a separate
904 directory. Then, using a simple program it would be possible to expand the
905 file to its original form even without GNU tar.
907 Bu default, v.1.0 archives are created. To use other formats,
908 --sparse-version option is provided. Additionally, v.0.0 can be obtained
909 by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
910 --pax-option delete=GNU.sparse.map
914 pax_sparse_member_p (struct tar_sparse_file
*file
)
916 return file
->stat_info
->sparse_map_avail
> 0
917 || file
->stat_info
->sparse_major
> 0;
921 pax_dump_header_0 (struct tar_sparse_file
*file
)
923 off_t block_ordinal
= current_block_ordinal ();
926 char nbuf
[UINTMAX_STRSIZE_BOUND
];
927 struct sp_array
*map
= file
->stat_info
->sparse_map
;
928 char *save_file_name
= NULL
;
930 /* Store the real file size */
931 xheader_store ("GNU.sparse.size", file
->stat_info
, NULL
);
932 xheader_store ("GNU.sparse.numblocks", file
->stat_info
, NULL
);
934 if (xheader_keyword_deleted_p ("GNU.sparse.map")
935 || tar_sparse_minor
== 0)
937 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
939 xheader_store ("GNU.sparse.offset", file
->stat_info
, &i
);
940 xheader_store ("GNU.sparse.numbytes", file
->stat_info
, &i
);
945 xheader_store ("GNU.sparse.name", file
->stat_info
, NULL
);
946 save_file_name
= file
->stat_info
->file_name
;
947 file
->stat_info
->file_name
= xheader_format_name (file
->stat_info
,
948 "%d/GNUSparseFile.%p/%f", 0);
950 xheader_string_begin (&file
->stat_info
->xhdr
);
951 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
954 xheader_string_add (&file
->stat_info
->xhdr
, ",");
955 xheader_string_add (&file
->stat_info
->xhdr
,
956 umaxtostr (map
[i
].offset
, nbuf
));
957 xheader_string_add (&file
->stat_info
->xhdr
, ",");
958 xheader_string_add (&file
->stat_info
->xhdr
,
959 umaxtostr (map
[i
].numbytes
, nbuf
));
961 if (!xheader_string_end (&file
->stat_info
->xhdr
,
964 free (file
->stat_info
->file_name
);
965 file
->stat_info
->file_name
= save_file_name
;
969 blk
= start_header (file
->stat_info
);
970 /* Store the effective (shrunken) file size */
971 OFF_TO_CHARS (file
->stat_info
->archive_file_size
, blk
->header
.size
);
972 finish_header (file
->stat_info
, blk
, block_ordinal
);
975 free (file
->stat_info
->file_name
);
976 file
->stat_info
->file_name
= save_file_name
;
982 pax_dump_header_1 (struct tar_sparse_file
*file
)
984 off_t block_ordinal
= current_block_ordinal ();
988 char nbuf
[UINTMAX_STRSIZE_BOUND
];
990 struct sp_array
*map
= file
->stat_info
->sparse_map
;
991 char *save_file_name
= file
->stat_info
->file_name
;
993 #define COPY_STRING(b,dst,src) do \
995 char *endp = b->buffer + BLOCKSIZE; \
996 char const *srcp = src; \
1001 set_next_block_after (b); \
1002 b = find_next_block (); \
1004 endp = b->buffer + BLOCKSIZE; \
1010 /* Compute stored file size */
1011 p
= umaxtostr (file
->stat_info
->sparse_map_avail
, nbuf
);
1012 size
+= strlen (p
) + 1;
1013 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
1015 p
= umaxtostr (map
[i
].offset
, nbuf
);
1016 size
+= strlen (p
) + 1;
1017 p
= umaxtostr (map
[i
].numbytes
, nbuf
);
1018 size
+= strlen (p
) + 1;
1020 size
= (size
+ BLOCKSIZE
- 1) / BLOCKSIZE
;
1021 file
->stat_info
->archive_file_size
+= size
* BLOCKSIZE
;
1022 file
->dumped_size
+= size
* BLOCKSIZE
;
1024 /* Store sparse file identification */
1025 xheader_store ("GNU.sparse.major", file
->stat_info
, NULL
);
1026 xheader_store ("GNU.sparse.minor", file
->stat_info
, NULL
);
1027 xheader_store ("GNU.sparse.name", file
->stat_info
, NULL
);
1028 xheader_store ("GNU.sparse.realsize", file
->stat_info
, NULL
);
1030 file
->stat_info
->file_name
= xheader_format_name (file
->stat_info
,
1031 "%d/GNUSparseFile.%p/%f", 0);
1033 blk
= start_header (file
->stat_info
);
1034 /* Store the effective (shrunken) file size */
1035 OFF_TO_CHARS (file
->stat_info
->archive_file_size
, blk
->header
.size
);
1036 finish_header (file
->stat_info
, blk
, block_ordinal
);
1037 free (file
->stat_info
->file_name
);
1038 file
->stat_info
->file_name
= save_file_name
;
1040 blk
= find_next_block ();
1042 p
= umaxtostr (file
->stat_info
->sparse_map_avail
, nbuf
);
1043 COPY_STRING (blk
, q
, p
);
1044 COPY_STRING (blk
, q
, "\n");
1045 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
1047 p
= umaxtostr (map
[i
].offset
, nbuf
);
1048 COPY_STRING (blk
, q
, p
);
1049 COPY_STRING (blk
, q
, "\n");
1050 p
= umaxtostr (map
[i
].numbytes
, nbuf
);
1051 COPY_STRING (blk
, q
, p
);
1052 COPY_STRING (blk
, q
, "\n");
1054 memset (q
, 0, BLOCKSIZE
- (q
- blk
->buffer
));
1055 set_next_block_after (blk
);
1060 pax_dump_header (struct tar_sparse_file
*file
)
1062 file
->stat_info
->sparse_major
= tar_sparse_major
;
1063 file
->stat_info
->sparse_minor
= tar_sparse_minor
;
1065 return (file
->stat_info
->sparse_major
== 0) ?
1066 pax_dump_header_0 (file
) : pax_dump_header_1 (file
);
1070 decode_num (uintmax_t *num
, char const *arg
, uintmax_t maxval
)
1075 if (!ISDIGIT (*arg
))
1078 u
= strtoumax (arg
, &arg_lim
, 10);
1080 if (! (u
<= maxval
&& errno
!= ERANGE
) || *arg_lim
)
1088 pax_decode_header (struct tar_sparse_file
*file
)
1090 if (file
->stat_info
->sparse_major
> 0)
1093 char nbuf
[UINTMAX_STRSIZE_BOUND
];
1098 #define COPY_BUF(b,buf,src) do \
1100 char *endp = b->buffer + BLOCKSIZE; \
1104 if (dst == buf + UINTMAX_STRSIZE_BOUND -1) \
1106 ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \
1107 file->stat_info->orig_file_name)); \
1112 set_next_block_after (b); \
1113 file->dumped_size += BLOCKSIZE; \
1114 b = find_next_block (); \
1116 endp = b->buffer + BLOCKSIZE; \
1120 while (*dst++ != '\n'); \
1124 set_next_block_after (current_header
);
1125 file
->dumped_size
+= BLOCKSIZE
;
1126 blk
= find_next_block ();
1128 COPY_BUF (blk
,nbuf
,p
);
1129 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (size_t)))
1131 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1132 file
->stat_info
->orig_file_name
));
1135 file
->stat_info
->sparse_map_size
= u
;
1136 file
->stat_info
->sparse_map
= xcalloc (file
->stat_info
->sparse_map_size
,
1137 sizeof (*file
->stat_info
->sparse_map
));
1138 file
->stat_info
->sparse_map_avail
= 0;
1139 for (i
= 0; i
< file
->stat_info
->sparse_map_size
; i
++)
1143 COPY_BUF (blk
,nbuf
,p
);
1144 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (off_t
)))
1146 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1147 file
->stat_info
->orig_file_name
));
1151 COPY_BUF (blk
,nbuf
,p
);
1152 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (off_t
)))
1154 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1155 file
->stat_info
->orig_file_name
));
1159 sparse_add_map (file
->stat_info
, &sp
);
1161 set_next_block_after (blk
);
1167 static struct tar_sparse_optab
const pax_optab
= {
1168 NULL
, /* No init function */
1169 NULL
, /* No done function */
1170 pax_sparse_member_p
,
1174 NULL
, /* No scan_block function */
1176 sparse_extract_region
,