1 /* Functions for dealing with sparse files
3 Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
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 3, or (at your option) any later
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.
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. */
24 struct tar_sparse_file;
25 static bool sparse_select_optab (struct tar_sparse_file *file);
27 enum sparse_scan_state
34 struct tar_sparse_optab
36 bool (*init) (struct tar_sparse_file *);
37 bool (*done) (struct tar_sparse_file *);
38 bool (*sparse_member_p) (struct tar_sparse_file *);
39 bool (*dump_header) (struct tar_sparse_file *);
40 bool (*fixup_header) (struct tar_sparse_file *);
41 bool (*decode_header) (struct tar_sparse_file *);
42 bool (*scan_block) (struct tar_sparse_file *, enum sparse_scan_state,
44 bool (*dump_region) (struct tar_sparse_file *, size_t);
45 bool (*extract_region) (struct tar_sparse_file *, size_t);
48 struct tar_sparse_file
50 int fd; /* File descriptor */
51 bool seekable; /* Is fd seekable? */
52 off_t offset; /* Current offset in fd if seekable==false.
54 off_t dumped_size; /* Number of bytes actually written
56 struct tar_stat_info *stat_info; /* Information about the file */
57 struct tar_sparse_optab const *optab; /* Operation table */
58 void *closure; /* Any additional data optab calls might
62 /* Dump zeros to file->fd until offset is reached. It is used instead of
63 lseek if the output file is not seekable */
65 dump_zeros (struct tar_sparse_file *file, off_t offset)
67 static char const zero_buf[BLOCKSIZE];
69 if (offset < file->offset)
75 while (file->offset < offset)
77 size_t size = (BLOCKSIZE < offset - file->offset
79 : offset - file->offset);
82 wrbytes = write (file->fd, zero_buf, size);
89 file->offset += wrbytes;
96 tar_sparse_member_p (struct tar_sparse_file *file)
98 if (file->optab->sparse_member_p)
99 return file->optab->sparse_member_p (file);
104 tar_sparse_init (struct tar_sparse_file *file)
106 memset (file, 0, sizeof *file);
108 if (!sparse_select_optab (file))
111 if (file->optab->init)
112 return file->optab->init (file);
118 tar_sparse_done (struct tar_sparse_file *file)
120 if (file->optab->done)
121 return file->optab->done (file);
126 tar_sparse_scan (struct tar_sparse_file *file, enum sparse_scan_state state,
129 if (file->optab->scan_block)
130 return file->optab->scan_block (file, state, block);
135 tar_sparse_dump_region (struct tar_sparse_file *file, size_t i)
137 if (file->optab->dump_region)
138 return file->optab->dump_region (file, i);
143 tar_sparse_extract_region (struct tar_sparse_file *file, size_t i)
145 if (file->optab->extract_region)
146 return file->optab->extract_region (file, i);
151 tar_sparse_dump_header (struct tar_sparse_file *file)
153 if (file->optab->dump_header)
154 return file->optab->dump_header (file);
159 tar_sparse_decode_header (struct tar_sparse_file *file)
161 if (file->optab->decode_header)
162 return file->optab->decode_header (file);
167 tar_sparse_fixup_header (struct tar_sparse_file *file)
169 if (file->optab->fixup_header)
170 return file->optab->fixup_header (file);
176 lseek_or_error (struct tar_sparse_file *file, off_t offset)
179 ? lseek (file->fd, offset, SEEK_SET) < 0
180 : ! dump_zeros (file, offset))
182 seek_diag_details (file->stat_info->orig_file_name, offset);
188 /* Takes a blockful of data and basically cruises through it to see if
189 it's made *entirely* of zeros, returning a 0 the instant it finds
190 something that is a nonzero, i.e., useful data. */
192 zero_block_p (char const *buffer, size_t size)
201 sparse_add_map (struct tar_stat_info *st, struct sp_array const *sp)
203 struct sp_array *sparse_map = st->sparse_map;
204 size_t avail = st->sparse_map_avail;
205 if (avail == st->sparse_map_size)
206 st->sparse_map = sparse_map =
207 x2nrealloc (sparse_map, &st->sparse_map_size, sizeof *sparse_map);
208 sparse_map[avail] = *sp;
209 st->sparse_map_avail = avail + 1;
212 /* Scan the sparse file and create its map */
214 sparse_scan_file (struct tar_sparse_file *file)
216 struct tar_stat_info *st = file->stat_info;
218 char buffer[BLOCKSIZE];
221 struct sp_array sp = {0, 0};
223 if (!lseek_or_error (file, 0))
226 st->archive_file_size = 0;
228 if (!tar_sparse_scan (file, scan_begin, NULL))
231 while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
232 && count != SAFE_READ_ERROR)
234 /* Analyze the block. */
235 if (zero_block_p (buffer, count))
239 sparse_add_map (st, &sp);
241 if (!tar_sparse_scan (file, scan_block, NULL))
247 if (sp.numbytes == 0)
249 sp.numbytes += count;
250 st->archive_file_size += count;
251 if (!tar_sparse_scan (file, scan_block, buffer))
258 if (sp.numbytes == 0)
261 sparse_add_map (st, &sp);
262 st->archive_file_size += count;
263 return tar_sparse_scan (file, scan_end, NULL);
266 static struct tar_sparse_optab const oldgnu_optab;
267 static struct tar_sparse_optab const star_optab;
268 static struct tar_sparse_optab const pax_optab;
271 sparse_select_optab (struct tar_sparse_file *file)
273 switch (current_format == DEFAULT_FORMAT ? archive_format : current_format)
280 case GNU_FORMAT: /*FIXME: This one should disappear? */
281 file->optab = &oldgnu_optab;
285 file->optab = &pax_optab;
289 file->optab = &star_optab;
299 sparse_dump_region (struct tar_sparse_file *file, size_t i)
302 off_t bytes_left = file->stat_info->sparse_map[i].numbytes;
304 if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
307 while (bytes_left > 0)
309 size_t bufsize = (bytes_left > BLOCKSIZE) ? BLOCKSIZE : bytes_left;
312 blk = find_next_block ();
313 bytes_read = safe_read (file->fd, blk->buffer, bufsize);
314 if (bytes_read == SAFE_READ_ERROR)
316 read_diag_details (file->stat_info->orig_file_name,
317 (file->stat_info->sparse_map[i].offset
318 + file->stat_info->sparse_map[i].numbytes
324 memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
325 bytes_left -= bytes_read;
326 file->dumped_size += bytes_read;
327 mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
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 (file.stat_info);
402 for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
403 rc = tar_sparse_dump_region (&file, i);
408 pad_archive (file.stat_info->archive_file_size - file.dumped_size);
409 return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
413 sparse_member_p (struct tar_stat_info *st)
415 struct tar_sparse_file file;
417 if (!tar_sparse_init (&file))
420 return tar_sparse_member_p (&file);
424 sparse_fixup_header (struct tar_stat_info *st)
426 struct tar_sparse_file file;
428 if (!tar_sparse_init (&file))
431 return tar_sparse_fixup_header (&file);
435 sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
438 struct tar_sparse_file file;
441 if (!tar_sparse_init (&file))
442 return dump_status_not_implemented;
446 file.seekable = lseek (fd, 0, SEEK_SET) == 0;
449 rc = tar_sparse_decode_header (&file);
450 for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
451 rc = tar_sparse_extract_region (&file, i);
452 *size = file.stat_info->archive_file_size - file.dumped_size;
453 return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
457 sparse_skip_file (struct tar_stat_info *st)
460 struct tar_sparse_file file;
462 if (!tar_sparse_init (&file))
463 return dump_status_not_implemented;
468 rc = tar_sparse_decode_header (&file);
469 skip_file (file.stat_info->archive_file_size - file.dumped_size);
470 return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
475 check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
477 if (!lseek_or_error (file, beg))
483 size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;
484 char diff_buffer[BLOCKSIZE];
486 bytes_read = safe_read (file->fd, diff_buffer, rdsize);
487 if (bytes_read == SAFE_READ_ERROR)
489 read_diag_details (file->stat_info->orig_file_name,
494 if (!zero_block_p (diff_buffer, bytes_read))
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));
509 check_data_region (struct tar_sparse_file *file, size_t i)
513 if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
515 size_left = file->stat_info->sparse_map[i].numbytes;
516 mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
518 while (size_left > 0)
521 size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
522 char diff_buffer[BLOCKSIZE];
524 union block *blk = find_next_block ();
527 ERROR ((0, 0, _("Unexpected EOF in archive")));
530 set_next_block_after (blk);
531 bytes_read = safe_read (file->fd, diff_buffer, rdsize);
532 if (bytes_read == SAFE_READ_ERROR)
534 read_diag_details (file->stat_info->orig_file_name,
535 (file->stat_info->sparse_map[i].offset
536 + file->stat_info->sparse_map[i].numbytes
541 file->dumped_size += bytes_read;
542 size_left -= bytes_read;
543 mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
544 if (memcmp (blk->buffer, diff_buffer, rdsize))
546 report_difference (file->stat_info, _("Contents differ"));
554 sparse_diff_file (int fd, struct tar_stat_info *st)
557 struct tar_sparse_file file;
561 if (!tar_sparse_init (&file))
562 return dump_status_not_implemented;
566 file.seekable = true; /* File *must* be seekable for compare to work */
568 rc = tar_sparse_decode_header (&file);
570 for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
572 rc = check_sparse_region (&file,
573 offset, file.stat_info->sparse_map[i].offset)
574 && check_data_region (&file, i);
575 offset = file.stat_info->sparse_map[i].offset
576 + file.stat_info->sparse_map[i].numbytes;
580 skip_file (file.stat_info->archive_file_size - file.dumped_size);
583 tar_sparse_done (&file);
588 /* Old GNU Format. The sparse file information is stored in the
589 oldgnu_header in the following manner:
591 The header is marked with type 'S'. Its `size' field contains
592 the cumulative size of all non-empty blocks of the file. The
593 actual file size is stored in `realsize' member of oldgnu_header.
595 The map of the file is stored in a list of `struct sparse'.
596 Each struct contains offset to the block of data and its
597 size (both as octal numbers). The first file header contains
598 at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map
599 contains more structs, then the field `isextended' of the main
600 header is set to 1 (binary) and the `struct sparse_header'
601 header follows, containing at most 21 following structs
602 (SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'
603 field of the extended header is set and next next extension header
606 enum oldgnu_add_status
614 oldgnu_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
616 return current_header->header.typeflag == GNUTYPE_SPARSE;
619 /* Add a sparse item to the sparse file and its obstack */
620 static enum oldgnu_add_status
621 oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
625 if (s->numbytes[0] == '\0')
627 sp.offset = OFF_FROM_HEADER (s->offset);
628 sp.numbytes = SIZE_FROM_HEADER (s->numbytes);
630 || file->stat_info->stat.st_size < sp.offset + sp.numbytes
631 || file->stat_info->archive_file_size < 0)
634 sparse_add_map (file->stat_info, &sp);
639 oldgnu_fixup_header (struct tar_sparse_file *file)
641 /* NOTE! st_size was initialized from the header
642 which actually contains archived size. The following fixes it */
643 file->stat_info->archive_file_size = file->stat_info->stat.st_size;
644 file->stat_info->stat.st_size =
645 OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
649 /* Convert old GNU format sparse data to internal representation */
651 oldgnu_get_sparse_info (struct tar_sparse_file *file)
654 union block *h = current_header;
656 enum oldgnu_add_status rc;
658 file->stat_info->sparse_map_avail = 0;
659 for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
661 rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
666 for (ext_p = h->oldgnu_header.isextended;
667 rc == add_ok && ext_p; ext_p = h->sparse_header.isextended)
669 h = find_next_block ();
672 ERROR ((0, 0, _("Unexpected EOF in archive")));
675 set_next_block_after (h);
676 for (i = 0; i < SPARSES_IN_SPARSE_HEADER && rc == add_ok; i++)
677 rc = oldgnu_add_sparse (file, &h->sparse_header.sp[i]);
682 ERROR ((0, 0, _("%s: invalid sparse archive member"),
683 file->stat_info->orig_file_name));
690 oldgnu_store_sparse_info (struct tar_sparse_file *file, size_t *pindex,
691 struct sparse *sp, size_t sparse_size)
693 for (; *pindex < file->stat_info->sparse_map_avail
694 && sparse_size > 0; sparse_size--, sp++, ++*pindex)
696 OFF_TO_CHARS (file->stat_info->sparse_map[*pindex].offset,
698 SIZE_TO_CHARS (file->stat_info->sparse_map[*pindex].numbytes,
704 oldgnu_dump_header (struct tar_sparse_file *file)
706 off_t block_ordinal = current_block_ordinal ();
710 blk = start_header (file->stat_info);
711 blk->header.typeflag = GNUTYPE_SPARSE;
712 if (file->stat_info->sparse_map_avail > SPARSES_IN_OLDGNU_HEADER)
713 blk->oldgnu_header.isextended = 1;
715 /* Store the real file size */
716 OFF_TO_CHARS (file->stat_info->stat.st_size, blk->oldgnu_header.realsize);
717 /* Store the effective (shrunken) file size */
718 OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
721 oldgnu_store_sparse_info (file, &i,
722 blk->oldgnu_header.sp,
723 SPARSES_IN_OLDGNU_HEADER);
724 blk->oldgnu_header.isextended = i < file->stat_info->sparse_map_avail;
725 finish_header (file->stat_info, blk, block_ordinal);
727 while (i < file->stat_info->sparse_map_avail)
729 blk = find_next_block ();
730 memset (blk->buffer, 0, BLOCKSIZE);
731 oldgnu_store_sparse_info (file, &i,
732 blk->sparse_header.sp,
733 SPARSES_IN_SPARSE_HEADER);
734 if (i < file->stat_info->sparse_map_avail)
735 blk->sparse_header.isextended = 1;
736 set_next_block_after (blk);
741 static struct tar_sparse_optab const oldgnu_optab = {
742 NULL, /* No init function */
743 NULL, /* No done function */
744 oldgnu_sparse_member_p,
747 oldgnu_get_sparse_info,
748 NULL, /* No scan_block function */
750 sparse_extract_region,
757 star_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
759 return current_header->header.typeflag == GNUTYPE_SPARSE;
763 star_fixup_header (struct tar_sparse_file *file)
765 /* NOTE! st_size was initialized from the header
766 which actually contains archived size. The following fixes it */
767 file->stat_info->archive_file_size = file->stat_info->stat.st_size;
768 file->stat_info->stat.st_size =
769 OFF_FROM_HEADER (current_header->star_in_header.realsize);
773 /* Convert STAR format sparse data to internal representation */
775 star_get_sparse_info (struct tar_sparse_file *file)
778 union block *h = current_header;
780 enum oldgnu_add_status rc = add_ok;
782 file->stat_info->sparse_map_avail = 0;
784 if (h->star_in_header.prefix[0] == '\0'
785 && h->star_in_header.sp[0].offset[10] != '\0')
787 /* Old star format */
788 for (i = 0; i < SPARSES_IN_STAR_HEADER; i++)
790 rc = oldgnu_add_sparse (file, &h->star_in_header.sp[i]);
794 ext_p = h->star_in_header.isextended;
799 for (; rc == add_ok && ext_p; ext_p = h->star_ext_header.isextended)
801 h = find_next_block ();
804 ERROR ((0, 0, _("Unexpected EOF in archive")));
807 set_next_block_after (h);
808 for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++)
809 rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]);
814 ERROR ((0, 0, _("%s: invalid sparse archive member"),
815 file->stat_info->orig_file_name));
822 static struct tar_sparse_optab const star_optab = {
823 NULL, /* No init function */
824 NULL, /* No done function */
825 star_sparse_member_p,
828 star_get_sparse_info,
829 NULL, /* No scan_block function */
830 NULL, /* No dump region function */
831 sparse_extract_region,
835 /* GNU PAX sparse file format. There are several versions:
839 The initial version of sparse format used by tar 1.14-1.15.1.
840 The sparse file map is stored in x header:
842 GNU.sparse.size Real size of the stored file
843 GNU.sparse.numblocks Number of blocks in the sparse map
844 repeat numblocks time
845 GNU.sparse.offset Offset of the next data block
846 GNU.sparse.numbytes Size of the next data block
849 This has been reported as conflicting with the POSIX specs. The reason is
850 that offsets and sizes of non-zero data blocks were stored in multiple
851 instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
852 POSIX requires the latest occurrence of the variable to override all
853 previous occurrences.
855 To avoid this incompatibility two following versions were introduced.
859 Used by tar 1.15.2 -- 1.15.91 (alpha releases).
861 The sparse file map is stored in
864 GNU.sparse.size Real size of the stored file
865 GNU.sparse.numblocks Number of blocks in the sparse map
866 GNU.sparse.map Map of non-null data chunks. A string consisting
867 of comma-separated values "offset,size[,offset,size]..."
869 The resulting GNU.sparse.map string can be *very* long. While POSIX does not
870 impose any limit on the length of a x header variable, this can confuse some
875 Starting from this version, the exact sparse format version is specified
876 explicitely in the header using the following variables:
878 GNU.sparse.major Major version
879 GNU.sparse.minor Minor version
881 X header keeps the following variables:
883 GNU.sparse.name Real file name of the sparse file
884 GNU.sparse.realsize Real size of the stored file (corresponds to the old
885 GNU.sparse.size variable)
887 The name field of the ustar header is constructed using the pattern
888 "%d/GNUSparseFile.%p/%f".
890 The sparse map itself is stored in the file data block, preceding the actual
891 file data. It consists of a series of octal numbers of arbitrary length,
892 delimited by newlines. The map is padded with nulls to the nearest block
895 The first number gives the number of entries in the map. Following are map
896 entries, each one consisting of two numbers giving the offset and size of
897 the data block it describes.
899 The format is designed in such a way that non-posix aware tars and tars not
900 supporting GNU.sparse.* keywords will extract each sparse file in its
901 condensed form with the file map attached and will place it into a separate
902 directory. Then, using a simple program it would be possible to expand the
903 file to its original form even without GNU tar.
905 Bu default, v.1.0 archives are created. To use other formats,
906 --sparse-version option is provided. Additionally, v.0.0 can be obtained
907 by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
908 --pax-option delete=GNU.sparse.map
912 pax_sparse_member_p (struct tar_sparse_file *file)
914 return file->stat_info->sparse_map_avail > 0
915 || file->stat_info->sparse_major > 0;
919 pax_dump_header_0 (struct tar_sparse_file *file)
921 off_t block_ordinal = current_block_ordinal ();
924 char nbuf[UINTMAX_STRSIZE_BOUND];
925 struct sp_array *map = file->stat_info->sparse_map;
926 char *save_file_name = NULL;
928 /* Store the real file size */
929 xheader_store ("GNU.sparse.size", file->stat_info, NULL);
930 xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
932 if (xheader_keyword_deleted_p ("GNU.sparse.map")
933 || tar_sparse_minor == 0)
935 for (i = 0; i < file->stat_info->sparse_map_avail; i++)
937 xheader_store ("GNU.sparse.offset", file->stat_info, &i);
938 xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
943 xheader_store ("GNU.sparse.name", file->stat_info, NULL);
944 save_file_name = file->stat_info->file_name;
945 file->stat_info->file_name = xheader_format_name (file->stat_info,
946 "%d/GNUSparseFile.%p/%f", 0);
948 xheader_string_begin (&file->stat_info->xhdr);
949 for (i = 0; i < file->stat_info->sparse_map_avail; i++)
952 xheader_string_add (&file->stat_info->xhdr, ",");
953 xheader_string_add (&file->stat_info->xhdr,
954 umaxtostr (map[i].offset, nbuf));
955 xheader_string_add (&file->stat_info->xhdr, ",");
956 xheader_string_add (&file->stat_info->xhdr,
957 umaxtostr (map[i].numbytes, nbuf));
959 if (!xheader_string_end (&file->stat_info->xhdr,
962 free (file->stat_info->file_name);
963 file->stat_info->file_name = save_file_name;
967 blk = start_header (file->stat_info);
968 /* Store the effective (shrunken) file size */
969 OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
970 finish_header (file->stat_info, blk, block_ordinal);
973 free (file->stat_info->file_name);
974 file->stat_info->file_name = save_file_name;
980 pax_dump_header_1 (struct tar_sparse_file *file)
982 off_t block_ordinal = current_block_ordinal ();
986 char nbuf[UINTMAX_STRSIZE_BOUND];
988 struct sp_array *map = file->stat_info->sparse_map;
989 char *save_file_name = file->stat_info->file_name;
991 #define COPY_STRING(b,dst,src) do \
993 char *endp = b->buffer + BLOCKSIZE; \
999 set_next_block_after (b); \
1000 b = find_next_block (); \
1002 endp = b->buffer + BLOCKSIZE; \
1008 /* Compute stored file size */
1009 p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
1010 size += strlen (p) + 1;
1011 for (i = 0; i < file->stat_info->sparse_map_avail; i++)
1013 p = umaxtostr (map[i].offset, nbuf);
1014 size += strlen (p) + 1;
1015 p = umaxtostr (map[i].numbytes, nbuf);
1016 size += strlen (p) + 1;
1018 size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
1019 file->stat_info->archive_file_size += size * BLOCKSIZE;
1020 file->dumped_size += size * BLOCKSIZE;
1022 /* Store sparse file identification */
1023 xheader_store ("GNU.sparse.major", file->stat_info, NULL);
1024 xheader_store ("GNU.sparse.minor", file->stat_info, NULL);
1025 xheader_store ("GNU.sparse.name", file->stat_info, NULL);
1026 xheader_store ("GNU.sparse.realsize", file->stat_info, NULL);
1028 file->stat_info->file_name = xheader_format_name (file->stat_info,
1029 "%d/GNUSparseFile.%p/%f", 0);
1031 blk = start_header (file->stat_info);
1032 /* Store the effective (shrunken) file size */
1033 OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
1034 finish_header (file->stat_info, blk, block_ordinal);
1035 free (file->stat_info->file_name);
1036 file->stat_info->file_name = save_file_name;
1038 blk = find_next_block ();
1040 p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
1041 COPY_STRING (blk, q, p);
1042 COPY_STRING (blk, q, "\n");
1043 for (i = 0; i < file->stat_info->sparse_map_avail; i++)
1045 p = umaxtostr (map[i].offset, nbuf);
1046 COPY_STRING (blk, q, p);
1047 COPY_STRING (blk, q, "\n");
1048 p = umaxtostr (map[i].numbytes, nbuf);
1049 COPY_STRING (blk, q, p);
1050 COPY_STRING (blk, q, "\n");
1052 memset (q, 0, BLOCKSIZE - (q - blk->buffer));
1053 set_next_block_after (blk);
1058 pax_dump_header (struct tar_sparse_file *file)
1060 file->stat_info->sparse_major = tar_sparse_major;
1061 file->stat_info->sparse_minor = tar_sparse_minor;
1063 return (file->stat_info->sparse_major == 0) ?
1064 pax_dump_header_0 (file) : pax_dump_header_1 (file);
1068 decode_num (uintmax_t *num, char const *arg, uintmax_t maxval)
1073 if (!ISDIGIT (*arg))
1076 u = strtoumax (arg, &arg_lim, 10);
1078 if (! (u <= maxval && errno != ERANGE) || *arg_lim)
1086 pax_decode_header (struct tar_sparse_file *file)
1088 if (file->stat_info->sparse_major > 0)
1091 char nbuf[UINTMAX_STRSIZE_BOUND];
1096 #define COPY_BUF(b,buf,src) do \
1098 char *endp = b->buffer + BLOCKSIZE; \
1102 if (dst == buf + UINTMAX_STRSIZE_BOUND -1) \
1104 ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \
1105 file->stat_info->orig_file_name)); \
1110 set_next_block_after (b); \
1111 file->dumped_size += BLOCKSIZE; \
1112 b = find_next_block (); \
1114 endp = b->buffer + BLOCKSIZE; \
1118 while (*dst++ != '\n'); \
1122 set_next_block_after (current_header);
1123 file->dumped_size += BLOCKSIZE;
1124 blk = find_next_block ();
1126 COPY_BUF (blk,nbuf,p);
1127 if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
1129 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1130 file->stat_info->orig_file_name));
1133 file->stat_info->sparse_map_size = u;
1134 file->stat_info->sparse_map = xcalloc (file->stat_info->sparse_map_size,
1135 sizeof (*file->stat_info->sparse_map));
1136 file->stat_info->sparse_map_avail = 0;
1137 for (i = 0; i < file->stat_info->sparse_map_size; i++)
1141 COPY_BUF (blk,nbuf,p);
1142 if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
1144 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1145 file->stat_info->orig_file_name));
1149 COPY_BUF (blk,nbuf,p);
1150 if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
1152 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1153 file->stat_info->orig_file_name));
1157 sparse_add_map (file->stat_info, &sp);
1159 set_next_block_after (blk);
1165 static struct tar_sparse_optab const pax_optab = {
1166 NULL, /* No init function */
1167 NULL, /* No done function */
1168 pax_sparse_member_p,
1172 NULL, /* No scan_block function */
1174 sparse_extract_region,