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 st
->archive_file_size
= 0;
226 if (ST_NBLOCKS (st
->stat
) == 0)
227 offset
= st
->stat
.st_size
;
230 if (!tar_sparse_scan (file
, scan_begin
, NULL
))
233 while ((count
= safe_read (fd
, buffer
, sizeof buffer
)) != 0
234 && count
!= SAFE_READ_ERROR
)
236 /* Analyze the block. */
237 if (zero_block_p (buffer
, count
))
241 sparse_add_map (st
, &sp
);
243 if (!tar_sparse_scan (file
, scan_block
, NULL
))
249 if (sp
.numbytes
== 0)
251 sp
.numbytes
+= count
;
252 st
->archive_file_size
+= count
;
253 if (!tar_sparse_scan (file
, scan_block
, buffer
))
261 if (sp
.numbytes
== 0)
264 sparse_add_map (st
, &sp
);
265 st
->archive_file_size
+= count
;
266 return tar_sparse_scan (file
, scan_end
, NULL
);
269 static struct tar_sparse_optab
const oldgnu_optab
;
270 static struct tar_sparse_optab
const star_optab
;
271 static struct tar_sparse_optab
const pax_optab
;
274 sparse_select_optab (struct tar_sparse_file
*file
)
276 switch (current_format
== DEFAULT_FORMAT
? archive_format
: current_format
)
283 case GNU_FORMAT
: /*FIXME: This one should disappear? */
284 file
->optab
= &oldgnu_optab
;
288 file
->optab
= &pax_optab
;
292 file
->optab
= &star_optab
;
302 sparse_dump_region (struct tar_sparse_file
*file
, size_t i
)
305 off_t bytes_left
= file
->stat_info
->sparse_map
[i
].numbytes
;
307 if (!lseek_or_error (file
, file
->stat_info
->sparse_map
[i
].offset
))
310 while (bytes_left
> 0)
312 size_t bufsize
= (bytes_left
> BLOCKSIZE
) ? BLOCKSIZE
: bytes_left
;
315 blk
= find_next_block ();
316 bytes_read
= safe_read (file
->fd
, blk
->buffer
, bufsize
);
317 if (bytes_read
== SAFE_READ_ERROR
)
319 read_diag_details (file
->stat_info
->orig_file_name
,
320 (file
->stat_info
->sparse_map
[i
].offset
321 + file
->stat_info
->sparse_map
[i
].numbytes
327 memset (blk
->buffer
+ bytes_read
, 0, BLOCKSIZE
- bytes_read
);
328 bytes_left
-= bytes_read
;
329 file
->dumped_size
+= bytes_read
;
330 set_next_block_after (blk
);
337 sparse_extract_region (struct tar_sparse_file
*file
, size_t i
)
341 if (!lseek_or_error (file
, file
->stat_info
->sparse_map
[i
].offset
))
344 write_size
= file
->stat_info
->sparse_map
[i
].numbytes
;
348 /* Last block of the file is a hole */
349 if (file
->seekable
&& sys_truncate (file
->fd
))
350 truncate_warn (file
->stat_info
->orig_file_name
);
352 else while (write_size
> 0)
355 size_t wrbytes
= (write_size
> BLOCKSIZE
) ? BLOCKSIZE
: write_size
;
356 union block
*blk
= find_next_block ();
359 ERROR ((0, 0, _("Unexpected EOF in archive")));
362 set_next_block_after (blk
);
363 count
= full_write (file
->fd
, blk
->buffer
, wrbytes
);
365 file
->dumped_size
+= count
;
366 mv_size_left (file
->stat_info
->archive_file_size
- file
->dumped_size
);
367 file
->offset
+= count
;
368 if (count
!= wrbytes
)
370 write_error_details (file
->stat_info
->orig_file_name
,
380 /* Interface functions */
382 sparse_dump_file (int fd
, struct tar_stat_info
*st
)
385 struct tar_sparse_file file
;
387 if (!tar_sparse_init (&file
))
388 return dump_status_not_implemented
;
392 file
.seekable
= true; /* File *must* be seekable for dump to work */
394 rc
= sparse_scan_file (&file
);
395 if (rc
&& file
.optab
->dump_region
)
397 tar_sparse_dump_header (&file
);
403 mv_begin_write (file
.stat_info
->file_name
,
404 file
.stat_info
->stat
.st_size
,
405 file
.stat_info
->archive_file_size
- file
.dumped_size
);
406 for (i
= 0; rc
&& i
< file
.stat_info
->sparse_map_avail
; i
++)
407 rc
= tar_sparse_dump_region (&file
, i
);
411 pad_archive (file
.stat_info
->archive_file_size
- file
.dumped_size
);
412 return (tar_sparse_done (&file
) && rc
) ? dump_status_ok
: dump_status_short
;
416 sparse_member_p (struct tar_stat_info
*st
)
418 struct tar_sparse_file file
;
420 if (!tar_sparse_init (&file
))
423 return tar_sparse_member_p (&file
);
427 sparse_fixup_header (struct tar_stat_info
*st
)
429 struct tar_sparse_file file
;
431 if (!tar_sparse_init (&file
))
434 return tar_sparse_fixup_header (&file
);
438 sparse_extract_file (int fd
, struct tar_stat_info
*st
, off_t
*size
)
441 struct tar_sparse_file file
;
444 if (!tar_sparse_init (&file
))
445 return dump_status_not_implemented
;
449 file
.seekable
= lseek (fd
, 0, SEEK_SET
) == 0;
452 rc
= tar_sparse_decode_header (&file
);
453 for (i
= 0; rc
&& i
< file
.stat_info
->sparse_map_avail
; i
++)
454 rc
= tar_sparse_extract_region (&file
, i
);
455 *size
= file
.stat_info
->archive_file_size
- file
.dumped_size
;
456 return (tar_sparse_done (&file
) && rc
) ? dump_status_ok
: dump_status_short
;
460 sparse_skip_file (struct tar_stat_info
*st
)
463 struct tar_sparse_file file
;
465 if (!tar_sparse_init (&file
))
466 return dump_status_not_implemented
;
471 rc
= tar_sparse_decode_header (&file
);
472 skip_file (file
.stat_info
->archive_file_size
- file
.dumped_size
);
473 return (tar_sparse_done (&file
) && rc
) ? dump_status_ok
: dump_status_short
;
478 check_sparse_region (struct tar_sparse_file
*file
, off_t beg
, off_t end
)
480 if (!lseek_or_error (file
, beg
))
486 size_t rdsize
= BLOCKSIZE
< end
- beg
? BLOCKSIZE
: end
- beg
;
487 char diff_buffer
[BLOCKSIZE
];
489 bytes_read
= safe_read (file
->fd
, diff_buffer
, rdsize
);
490 if (bytes_read
== SAFE_READ_ERROR
)
492 read_diag_details (file
->stat_info
->orig_file_name
,
497 if (!zero_block_p (diff_buffer
, bytes_read
))
499 char begbuf
[INT_BUFSIZE_BOUND (off_t
)];
500 report_difference (file
->stat_info
,
501 _("File fragment at %s is not a hole"),
502 offtostr (beg
, begbuf
));
512 check_data_region (struct tar_sparse_file
*file
, size_t i
)
516 if (!lseek_or_error (file
, file
->stat_info
->sparse_map
[i
].offset
))
518 size_left
= file
->stat_info
->sparse_map
[i
].numbytes
;
519 mv_size_left (file
->stat_info
->archive_file_size
- file
->dumped_size
);
521 while (size_left
> 0)
524 size_t rdsize
= (size_left
> BLOCKSIZE
) ? BLOCKSIZE
: size_left
;
525 char diff_buffer
[BLOCKSIZE
];
527 union block
*blk
= find_next_block ();
530 ERROR ((0, 0, _("Unexpected EOF in archive")));
533 set_next_block_after (blk
);
534 bytes_read
= safe_read (file
->fd
, diff_buffer
, rdsize
);
535 if (bytes_read
== SAFE_READ_ERROR
)
537 read_diag_details (file
->stat_info
->orig_file_name
,
538 (file
->stat_info
->sparse_map
[i
].offset
539 + file
->stat_info
->sparse_map
[i
].numbytes
544 file
->dumped_size
+= bytes_read
;
545 size_left
-= bytes_read
;
546 mv_size_left (file
->stat_info
->archive_file_size
- file
->dumped_size
);
547 if (memcmp (blk
->buffer
, diff_buffer
, rdsize
))
549 report_difference (file
->stat_info
, _("Contents differ"));
557 sparse_diff_file (int fd
, struct tar_stat_info
*st
)
560 struct tar_sparse_file file
;
564 if (!tar_sparse_init (&file
))
565 return dump_status_not_implemented
;
569 file
.seekable
= true; /* File *must* be seekable for compare to work */
571 rc
= tar_sparse_decode_header (&file
);
573 for (i
= 0; rc
&& i
< file
.stat_info
->sparse_map_avail
; i
++)
575 rc
= check_sparse_region (&file
,
576 offset
, file
.stat_info
->sparse_map
[i
].offset
)
577 && check_data_region (&file
, i
);
578 offset
= file
.stat_info
->sparse_map
[i
].offset
579 + file
.stat_info
->sparse_map
[i
].numbytes
;
583 skip_file (file
.stat_info
->archive_file_size
- file
.dumped_size
);
586 tar_sparse_done (&file
);
591 /* Old GNU Format. The sparse file information is stored in the
592 oldgnu_header in the following manner:
594 The header is marked with type 'S'. Its `size' field contains
595 the cumulative size of all non-empty blocks of the file. The
596 actual file size is stored in `realsize' member of oldgnu_header.
598 The map of the file is stored in a list of `struct sparse'.
599 Each struct contains offset to the block of data and its
600 size (both as octal numbers). The first file header contains
601 at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map
602 contains more structs, then the field `isextended' of the main
603 header is set to 1 (binary) and the `struct sparse_header'
604 header follows, containing at most 21 following structs
605 (SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'
606 field of the extended header is set and next next extension header
609 enum oldgnu_add_status
617 oldgnu_sparse_member_p (struct tar_sparse_file
*file
__attribute__ ((unused
)))
619 return current_header
->header
.typeflag
== GNUTYPE_SPARSE
;
622 /* Add a sparse item to the sparse file and its obstack */
623 static enum oldgnu_add_status
624 oldgnu_add_sparse (struct tar_sparse_file
*file
, struct sparse
*s
)
628 if (s
->numbytes
[0] == '\0')
630 sp
.offset
= OFF_FROM_HEADER (s
->offset
);
631 sp
.numbytes
= OFF_FROM_HEADER (s
->numbytes
);
633 || sp
.offset
+ sp
.numbytes
< 0
634 || file
->stat_info
->stat
.st_size
< sp
.offset
+ sp
.numbytes
635 || file
->stat_info
->archive_file_size
< 0)
638 sparse_add_map (file
->stat_info
, &sp
);
643 oldgnu_fixup_header (struct tar_sparse_file
*file
)
645 /* NOTE! st_size was initialized from the header
646 which actually contains archived size. The following fixes it */
647 file
->stat_info
->archive_file_size
= file
->stat_info
->stat
.st_size
;
648 file
->stat_info
->stat
.st_size
=
649 OFF_FROM_HEADER (current_header
->oldgnu_header
.realsize
);
653 /* Convert old GNU format sparse data to internal representation */
655 oldgnu_get_sparse_info (struct tar_sparse_file
*file
)
658 union block
*h
= current_header
;
660 enum oldgnu_add_status rc
;
662 file
->stat_info
->sparse_map_avail
= 0;
663 for (i
= 0; i
< SPARSES_IN_OLDGNU_HEADER
; i
++)
665 rc
= oldgnu_add_sparse (file
, &h
->oldgnu_header
.sp
[i
]);
670 for (ext_p
= h
->oldgnu_header
.isextended
;
671 rc
== add_ok
&& ext_p
; ext_p
= h
->sparse_header
.isextended
)
673 h
= find_next_block ();
676 ERROR ((0, 0, _("Unexpected EOF in archive")));
679 set_next_block_after (h
);
680 for (i
= 0; i
< SPARSES_IN_SPARSE_HEADER
&& rc
== add_ok
; i
++)
681 rc
= oldgnu_add_sparse (file
, &h
->sparse_header
.sp
[i
]);
686 ERROR ((0, 0, _("%s: invalid sparse archive member"),
687 file
->stat_info
->orig_file_name
));
694 oldgnu_store_sparse_info (struct tar_sparse_file
*file
, size_t *pindex
,
695 struct sparse
*sp
, size_t sparse_size
)
697 for (; *pindex
< file
->stat_info
->sparse_map_avail
698 && sparse_size
> 0; sparse_size
--, sp
++, ++*pindex
)
700 OFF_TO_CHARS (file
->stat_info
->sparse_map
[*pindex
].offset
,
702 OFF_TO_CHARS (file
->stat_info
->sparse_map
[*pindex
].numbytes
,
708 oldgnu_dump_header (struct tar_sparse_file
*file
)
710 off_t block_ordinal
= current_block_ordinal ();
714 blk
= start_header (file
->stat_info
);
715 blk
->header
.typeflag
= GNUTYPE_SPARSE
;
716 if (file
->stat_info
->sparse_map_avail
> SPARSES_IN_OLDGNU_HEADER
)
717 blk
->oldgnu_header
.isextended
= 1;
719 /* Store the real file size */
720 OFF_TO_CHARS (file
->stat_info
->stat
.st_size
, blk
->oldgnu_header
.realsize
);
721 /* Store the effective (shrunken) file size */
722 OFF_TO_CHARS (file
->stat_info
->archive_file_size
, blk
->header
.size
);
725 oldgnu_store_sparse_info (file
, &i
,
726 blk
->oldgnu_header
.sp
,
727 SPARSES_IN_OLDGNU_HEADER
);
728 blk
->oldgnu_header
.isextended
= i
< file
->stat_info
->sparse_map_avail
;
729 finish_header (file
->stat_info
, blk
, block_ordinal
);
731 while (i
< file
->stat_info
->sparse_map_avail
)
733 blk
= find_next_block ();
734 memset (blk
->buffer
, 0, BLOCKSIZE
);
735 oldgnu_store_sparse_info (file
, &i
,
736 blk
->sparse_header
.sp
,
737 SPARSES_IN_SPARSE_HEADER
);
738 if (i
< file
->stat_info
->sparse_map_avail
)
739 blk
->sparse_header
.isextended
= 1;
740 set_next_block_after (blk
);
745 static struct tar_sparse_optab
const oldgnu_optab
= {
746 NULL
, /* No init function */
747 NULL
, /* No done function */
748 oldgnu_sparse_member_p
,
751 oldgnu_get_sparse_info
,
752 NULL
, /* No scan_block function */
754 sparse_extract_region
,
761 star_sparse_member_p (struct tar_sparse_file
*file
__attribute__ ((unused
)))
763 return current_header
->header
.typeflag
== GNUTYPE_SPARSE
;
767 star_fixup_header (struct tar_sparse_file
*file
)
769 /* NOTE! st_size was initialized from the header
770 which actually contains archived size. The following fixes it */
771 file
->stat_info
->archive_file_size
= file
->stat_info
->stat
.st_size
;
772 file
->stat_info
->stat
.st_size
=
773 OFF_FROM_HEADER (current_header
->star_in_header
.realsize
);
777 /* Convert STAR format sparse data to internal representation */
779 star_get_sparse_info (struct tar_sparse_file
*file
)
782 union block
*h
= current_header
;
784 enum oldgnu_add_status rc
= add_ok
;
786 file
->stat_info
->sparse_map_avail
= 0;
788 if (h
->star_in_header
.prefix
[0] == '\0'
789 && h
->star_in_header
.sp
[0].offset
[10] != '\0')
791 /* Old star format */
792 for (i
= 0; i
< SPARSES_IN_STAR_HEADER
; i
++)
794 rc
= oldgnu_add_sparse (file
, &h
->star_in_header
.sp
[i
]);
798 ext_p
= h
->star_in_header
.isextended
;
803 for (; rc
== add_ok
&& ext_p
; ext_p
= h
->star_ext_header
.isextended
)
805 h
= find_next_block ();
808 ERROR ((0, 0, _("Unexpected EOF in archive")));
811 set_next_block_after (h
);
812 for (i
= 0; i
< SPARSES_IN_STAR_EXT_HEADER
&& rc
== add_ok
; i
++)
813 rc
= oldgnu_add_sparse (file
, &h
->star_ext_header
.sp
[i
]);
818 ERROR ((0, 0, _("%s: invalid sparse archive member"),
819 file
->stat_info
->orig_file_name
));
826 static struct tar_sparse_optab
const star_optab
= {
827 NULL
, /* No init function */
828 NULL
, /* No done function */
829 star_sparse_member_p
,
832 star_get_sparse_info
,
833 NULL
, /* No scan_block function */
834 NULL
, /* No dump region function */
835 sparse_extract_region
,
839 /* GNU PAX sparse file format. There are several versions:
843 The initial version of sparse format used by tar 1.14-1.15.1.
844 The sparse file map is stored in x header:
846 GNU.sparse.size Real size of the stored file
847 GNU.sparse.numblocks Number of blocks in the sparse map
848 repeat numblocks time
849 GNU.sparse.offset Offset of the next data block
850 GNU.sparse.numbytes Size of the next data block
853 This has been reported as conflicting with the POSIX specs. The reason is
854 that offsets and sizes of non-zero data blocks were stored in multiple
855 instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
856 POSIX requires the latest occurrence of the variable to override all
857 previous occurrences.
859 To avoid this incompatibility two following versions were introduced.
863 Used by tar 1.15.2 -- 1.15.91 (alpha releases).
865 The sparse file map is stored in
868 GNU.sparse.size Real size of the stored file
869 GNU.sparse.numblocks Number of blocks in the sparse map
870 GNU.sparse.map Map of non-null data chunks. A string consisting
871 of comma-separated values "offset,size[,offset,size]..."
873 The resulting GNU.sparse.map string can be *very* long. While POSIX does not
874 impose any limit on the length of a x header variable, this can confuse some
879 Starting from this version, the exact sparse format version is specified
880 explicitely in the header using the following variables:
882 GNU.sparse.major Major version
883 GNU.sparse.minor Minor version
885 X header keeps the following variables:
887 GNU.sparse.name Real file name of the sparse file
888 GNU.sparse.realsize Real size of the stored file (corresponds to the old
889 GNU.sparse.size variable)
891 The name field of the ustar header is constructed using the pattern
892 "%d/GNUSparseFile.%p/%f".
894 The sparse map itself is stored in the file data block, preceding the actual
895 file data. It consists of a series of octal numbers of arbitrary length,
896 delimited by newlines. The map is padded with nulls to the nearest block
899 The first number gives the number of entries in the map. Following are map
900 entries, each one consisting of two numbers giving the offset and size of
901 the data block it describes.
903 The format is designed in such a way that non-posix aware tars and tars not
904 supporting GNU.sparse.* keywords will extract each sparse file in its
905 condensed form with the file map attached and will place it into a separate
906 directory. Then, using a simple program it would be possible to expand the
907 file to its original form even without GNU tar.
909 Bu default, v.1.0 archives are created. To use other formats,
910 --sparse-version option is provided. Additionally, v.0.0 can be obtained
911 by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
912 --pax-option delete=GNU.sparse.map
916 pax_sparse_member_p (struct tar_sparse_file
*file
)
918 return file
->stat_info
->sparse_map_avail
> 0
919 || file
->stat_info
->sparse_major
> 0;
923 pax_dump_header_0 (struct tar_sparse_file
*file
)
925 off_t block_ordinal
= current_block_ordinal ();
928 char nbuf
[UINTMAX_STRSIZE_BOUND
];
929 struct sp_array
*map
= file
->stat_info
->sparse_map
;
930 char *save_file_name
= NULL
;
932 /* Store the real file size */
933 xheader_store ("GNU.sparse.size", file
->stat_info
, NULL
);
934 xheader_store ("GNU.sparse.numblocks", file
->stat_info
, NULL
);
936 if (xheader_keyword_deleted_p ("GNU.sparse.map")
937 || tar_sparse_minor
== 0)
939 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
941 xheader_store ("GNU.sparse.offset", file
->stat_info
, &i
);
942 xheader_store ("GNU.sparse.numbytes", file
->stat_info
, &i
);
947 xheader_store ("GNU.sparse.name", file
->stat_info
, NULL
);
948 save_file_name
= file
->stat_info
->file_name
;
949 file
->stat_info
->file_name
= xheader_format_name (file
->stat_info
,
950 "%d/GNUSparseFile.%p/%f", 0);
952 xheader_string_begin (&file
->stat_info
->xhdr
);
953 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
956 xheader_string_add (&file
->stat_info
->xhdr
, ",");
957 xheader_string_add (&file
->stat_info
->xhdr
,
958 umaxtostr (map
[i
].offset
, nbuf
));
959 xheader_string_add (&file
->stat_info
->xhdr
, ",");
960 xheader_string_add (&file
->stat_info
->xhdr
,
961 umaxtostr (map
[i
].numbytes
, nbuf
));
963 if (!xheader_string_end (&file
->stat_info
->xhdr
,
966 free (file
->stat_info
->file_name
);
967 file
->stat_info
->file_name
= save_file_name
;
971 blk
= start_header (file
->stat_info
);
972 /* Store the effective (shrunken) file size */
973 OFF_TO_CHARS (file
->stat_info
->archive_file_size
, blk
->header
.size
);
974 finish_header (file
->stat_info
, blk
, block_ordinal
);
977 free (file
->stat_info
->file_name
);
978 file
->stat_info
->file_name
= save_file_name
;
984 pax_dump_header_1 (struct tar_sparse_file
*file
)
986 off_t block_ordinal
= current_block_ordinal ();
990 char nbuf
[UINTMAX_STRSIZE_BOUND
];
992 struct sp_array
*map
= file
->stat_info
->sparse_map
;
993 char *save_file_name
= file
->stat_info
->file_name
;
995 #define COPY_STRING(b,dst,src) do \
997 char *endp = b->buffer + BLOCKSIZE; \
998 char const *srcp = src; \
1003 set_next_block_after (b); \
1004 b = find_next_block (); \
1006 endp = b->buffer + BLOCKSIZE; \
1012 /* Compute stored file size */
1013 p
= umaxtostr (file
->stat_info
->sparse_map_avail
, nbuf
);
1014 size
+= strlen (p
) + 1;
1015 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
1017 p
= umaxtostr (map
[i
].offset
, nbuf
);
1018 size
+= strlen (p
) + 1;
1019 p
= umaxtostr (map
[i
].numbytes
, nbuf
);
1020 size
+= strlen (p
) + 1;
1022 size
= (size
+ BLOCKSIZE
- 1) / BLOCKSIZE
;
1023 file
->stat_info
->archive_file_size
+= size
* BLOCKSIZE
;
1024 file
->dumped_size
+= size
* BLOCKSIZE
;
1026 /* Store sparse file identification */
1027 xheader_store ("GNU.sparse.major", file
->stat_info
, NULL
);
1028 xheader_store ("GNU.sparse.minor", file
->stat_info
, NULL
);
1029 xheader_store ("GNU.sparse.name", file
->stat_info
, NULL
);
1030 xheader_store ("GNU.sparse.realsize", file
->stat_info
, NULL
);
1032 file
->stat_info
->file_name
= xheader_format_name (file
->stat_info
,
1033 "%d/GNUSparseFile.%p/%f", 0);
1035 blk
= start_header (file
->stat_info
);
1036 /* Store the effective (shrunken) file size */
1037 OFF_TO_CHARS (file
->stat_info
->archive_file_size
, blk
->header
.size
);
1038 finish_header (file
->stat_info
, blk
, block_ordinal
);
1039 free (file
->stat_info
->file_name
);
1040 file
->stat_info
->file_name
= save_file_name
;
1042 blk
= find_next_block ();
1044 p
= umaxtostr (file
->stat_info
->sparse_map_avail
, nbuf
);
1045 COPY_STRING (blk
, q
, p
);
1046 COPY_STRING (blk
, q
, "\n");
1047 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
1049 p
= umaxtostr (map
[i
].offset
, nbuf
);
1050 COPY_STRING (blk
, q
, p
);
1051 COPY_STRING (blk
, q
, "\n");
1052 p
= umaxtostr (map
[i
].numbytes
, nbuf
);
1053 COPY_STRING (blk
, q
, p
);
1054 COPY_STRING (blk
, q
, "\n");
1056 memset (q
, 0, BLOCKSIZE
- (q
- blk
->buffer
));
1057 set_next_block_after (blk
);
1062 pax_dump_header (struct tar_sparse_file
*file
)
1064 file
->stat_info
->sparse_major
= tar_sparse_major
;
1065 file
->stat_info
->sparse_minor
= tar_sparse_minor
;
1067 return (file
->stat_info
->sparse_major
== 0) ?
1068 pax_dump_header_0 (file
) : pax_dump_header_1 (file
);
1072 decode_num (uintmax_t *num
, char const *arg
, uintmax_t maxval
)
1077 if (!ISDIGIT (*arg
))
1080 u
= strtoumax (arg
, &arg_lim
, 10);
1082 if (! (u
<= maxval
&& errno
!= ERANGE
) || *arg_lim
)
1090 pax_decode_header (struct tar_sparse_file
*file
)
1092 if (file
->stat_info
->sparse_major
> 0)
1095 char nbuf
[UINTMAX_STRSIZE_BOUND
];
1100 #define COPY_BUF(b,buf,src) do \
1102 char *endp = b->buffer + BLOCKSIZE; \
1106 if (dst == buf + UINTMAX_STRSIZE_BOUND -1) \
1108 ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \
1109 file->stat_info->orig_file_name)); \
1114 set_next_block_after (b); \
1115 file->dumped_size += BLOCKSIZE; \
1116 b = find_next_block (); \
1118 endp = b->buffer + BLOCKSIZE; \
1122 while (*dst++ != '\n'); \
1126 set_next_block_after (current_header
);
1127 file
->dumped_size
+= BLOCKSIZE
;
1128 blk
= find_next_block ();
1130 COPY_BUF (blk
,nbuf
,p
);
1131 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (size_t)))
1133 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1134 file
->stat_info
->orig_file_name
));
1137 file
->stat_info
->sparse_map_size
= u
;
1138 file
->stat_info
->sparse_map
= xcalloc (file
->stat_info
->sparse_map_size
,
1139 sizeof (*file
->stat_info
->sparse_map
));
1140 file
->stat_info
->sparse_map_avail
= 0;
1141 for (i
= 0; i
< file
->stat_info
->sparse_map_size
; i
++)
1145 COPY_BUF (blk
,nbuf
,p
);
1146 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (off_t
)))
1148 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1149 file
->stat_info
->orig_file_name
));
1153 COPY_BUF (blk
,nbuf
,p
);
1154 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (off_t
)))
1156 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1157 file
->stat_info
->orig_file_name
));
1161 sparse_add_map (file
->stat_info
, &sp
);
1163 set_next_block_after (blk
);
1169 static struct tar_sparse_optab
const pax_optab
= {
1170 NULL
, /* No init function */
1171 NULL
, /* No done function */
1172 pax_sparse_member_p
,
1176 NULL
, /* No scan_block function */
1178 sparse_extract_region
,