1 /* Functions for dealing with sparse files
3 Copyright 2003-2007, 2010, 2013-2014 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, see <http://www.gnu.org/licenses/>. */
23 struct tar_sparse_file
;
24 static bool sparse_select_optab (struct tar_sparse_file
*file
);
26 enum sparse_scan_state
33 struct tar_sparse_optab
35 bool (*init
) (struct tar_sparse_file
*);
36 bool (*done
) (struct tar_sparse_file
*);
37 bool (*sparse_member_p
) (struct tar_sparse_file
*);
38 bool (*dump_header
) (struct tar_sparse_file
*);
39 bool (*fixup_header
) (struct tar_sparse_file
*);
40 bool (*decode_header
) (struct tar_sparse_file
*);
41 bool (*scan_block
) (struct tar_sparse_file
*, enum sparse_scan_state
,
43 bool (*dump_region
) (struct tar_sparse_file
*, size_t);
44 bool (*extract_region
) (struct tar_sparse_file
*, size_t);
47 struct tar_sparse_file
49 int fd
; /* File descriptor */
50 bool seekable
; /* Is fd seekable? */
51 off_t offset
; /* Current offset in fd if seekable==false.
53 off_t dumped_size
; /* Number of bytes actually written
55 struct tar_stat_info
*stat_info
; /* Information about the file */
56 struct tar_sparse_optab
const *optab
; /* Operation table */
57 void *closure
; /* Any additional data optab calls might
61 /* Dump zeros to file->fd until offset is reached. It is used instead of
62 lseek if the output file is not seekable */
64 dump_zeros (struct tar_sparse_file
*file
, off_t offset
)
66 static char const zero_buf
[BLOCKSIZE
];
68 if (offset
< file
->offset
)
74 while (file
->offset
< offset
)
76 size_t size
= (BLOCKSIZE
< offset
- file
->offset
78 : offset
- file
->offset
);
81 wrbytes
= write (file
->fd
, zero_buf
, size
);
88 file
->offset
+= wrbytes
;
95 tar_sparse_member_p (struct tar_sparse_file
*file
)
97 if (file
->optab
->sparse_member_p
)
98 return file
->optab
->sparse_member_p (file
);
103 tar_sparse_init (struct tar_sparse_file
*file
)
105 memset (file
, 0, sizeof *file
);
107 if (!sparse_select_optab (file
))
110 if (file
->optab
->init
)
111 return file
->optab
->init (file
);
117 tar_sparse_done (struct tar_sparse_file
*file
)
119 if (file
->optab
->done
)
120 return file
->optab
->done (file
);
125 tar_sparse_scan (struct tar_sparse_file
*file
, enum sparse_scan_state state
,
128 if (file
->optab
->scan_block
)
129 return file
->optab
->scan_block (file
, state
, block
);
134 tar_sparse_dump_region (struct tar_sparse_file
*file
, size_t i
)
136 if (file
->optab
->dump_region
)
137 return file
->optab
->dump_region (file
, i
);
142 tar_sparse_extract_region (struct tar_sparse_file
*file
, size_t i
)
144 if (file
->optab
->extract_region
)
145 return file
->optab
->extract_region (file
, i
);
150 tar_sparse_dump_header (struct tar_sparse_file
*file
)
152 if (file
->optab
->dump_header
)
153 return file
->optab
->dump_header (file
);
158 tar_sparse_decode_header (struct tar_sparse_file
*file
)
160 if (file
->optab
->decode_header
)
161 return file
->optab
->decode_header (file
);
166 tar_sparse_fixup_header (struct tar_sparse_file
*file
)
168 if (file
->optab
->fixup_header
)
169 return file
->optab
->fixup_header (file
);
175 lseek_or_error (struct tar_sparse_file
*file
, off_t offset
)
178 ? lseek (file
->fd
, offset
, SEEK_SET
) < 0
179 : ! dump_zeros (file
, offset
))
181 seek_diag_details (file
->stat_info
->orig_file_name
, offset
);
187 /* Takes a blockful of data and basically cruises through it to see if
188 it's made *entirely* of zeros, returning a 0 the instant it finds
189 something that is a nonzero, i.e., useful data. */
191 zero_block_p (char const *buffer
, size_t size
)
200 sparse_add_map (struct tar_stat_info
*st
, struct sp_array
const *sp
)
202 struct sp_array
*sparse_map
= st
->sparse_map
;
203 size_t avail
= st
->sparse_map_avail
;
204 if (avail
== st
->sparse_map_size
)
205 st
->sparse_map
= sparse_map
=
206 x2nrealloc (sparse_map
, &st
->sparse_map_size
, sizeof *sparse_map
);
207 sparse_map
[avail
] = *sp
;
208 st
->sparse_map_avail
= avail
+ 1;
211 /* Scan the sparse file and create its map */
213 sparse_scan_file (struct tar_sparse_file
*file
)
215 struct tar_stat_info
*st
= file
->stat_info
;
217 char buffer
[BLOCKSIZE
];
220 struct sp_array sp
= {0, 0};
222 st
->archive_file_size
= 0;
224 if (ST_NBLOCKS (st
->stat
) == 0)
225 offset
= st
->stat
.st_size
;
228 if (!tar_sparse_scan (file
, scan_begin
, NULL
))
231 while ((count
= blocking_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
))
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
= blocking_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
);
630 if (sp
.offset
< 0 || sp
.numbytes
< 0
631 || INT_ADD_OVERFLOW (sp
.offset
, sp
.numbytes
)
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 off_t realsize
= OFF_FROM_HEADER (current_header
->oldgnu_header
.realsize
);
646 file
->stat_info
->archive_file_size
= file
->stat_info
->stat
.st_size
;
647 file
->stat_info
->stat
.st_size
= max (0, realsize
);
648 return 0 <= 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 off_t realsize
= OFF_FROM_HEADER (current_header
->star_in_header
.realsize
);
770 file
->stat_info
->archive_file_size
= file
->stat_info
->stat
.st_size
;
771 file
->stat_info
->stat
.st_size
= max (0, realsize
);
772 return 0 <= 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
]);
812 file
->dumped_size
+= BLOCKSIZE
;
817 ERROR ((0, 0, _("%s: invalid sparse archive member"),
818 file
->stat_info
->orig_file_name
));
825 static struct tar_sparse_optab
const star_optab
= {
826 NULL
, /* No init function */
827 NULL
, /* No done function */
828 star_sparse_member_p
,
831 star_get_sparse_info
,
832 NULL
, /* No scan_block function */
833 NULL
, /* No dump region function */
834 sparse_extract_region
,
838 /* GNU PAX sparse file format. There are several versions:
842 The initial version of sparse format used by tar 1.14-1.15.1.
843 The sparse file map is stored in x header:
845 GNU.sparse.size Real size of the stored file
846 GNU.sparse.numblocks Number of blocks in the sparse map
847 repeat numblocks time
848 GNU.sparse.offset Offset of the next data block
849 GNU.sparse.numbytes Size of the next data block
852 This has been reported as conflicting with the POSIX specs. The reason is
853 that offsets and sizes of non-zero data blocks were stored in multiple
854 instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
855 POSIX requires the latest occurrence of the variable to override all
856 previous occurrences.
858 To avoid this incompatibility two following versions were introduced.
862 Used by tar 1.15.2 -- 1.15.91 (alpha releases).
864 The sparse file map is stored in
867 GNU.sparse.size Real size of the stored file
868 GNU.sparse.numblocks Number of blocks in the sparse map
869 GNU.sparse.map Map of non-null data chunks. A string consisting
870 of comma-separated values "offset,size[,offset,size]..."
872 The resulting GNU.sparse.map string can be *very* long. While POSIX does not
873 impose any limit on the length of a x header variable, this can confuse some
878 Starting from this version, the exact sparse format version is specified
879 explicitely in the header using the following variables:
881 GNU.sparse.major Major version
882 GNU.sparse.minor Minor version
884 X header keeps the following variables:
886 GNU.sparse.name Real file name of the sparse file
887 GNU.sparse.realsize Real size of the stored file (corresponds to the old
888 GNU.sparse.size variable)
890 The name field of the ustar header is constructed using the pattern
891 "%d/GNUSparseFile.%p/%f".
893 The sparse map itself is stored in the file data block, preceding the actual
894 file data. It consists of a series of octal numbers of arbitrary length,
895 delimited by newlines. The map is padded with nulls to the nearest block
898 The first number gives the number of entries in the map. Following are map
899 entries, each one consisting of two numbers giving the offset and size of
900 the data block it describes.
902 The format is designed in such a way that non-posix aware tars and tars not
903 supporting GNU.sparse.* keywords will extract each sparse file in its
904 condensed form with the file map attached and will place it into a separate
905 directory. Then, using a simple program it would be possible to expand the
906 file to its original form even without GNU tar.
908 Bu default, v.1.0 archives are created. To use other formats,
909 --sparse-version option is provided. Additionally, v.0.0 can be obtained
910 by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
911 --pax-option delete=GNU.sparse.map
915 pax_sparse_member_p (struct tar_sparse_file
*file
)
917 return file
->stat_info
->sparse_map_avail
> 0
918 || file
->stat_info
->sparse_major
> 0;
921 /* Start a header that uses the effective (shrunken) file size. */
923 pax_start_header (struct tar_stat_info
*st
)
925 off_t realsize
= st
->stat
.st_size
;
927 st
->stat
.st_size
= st
->archive_file_size
;
928 blk
= start_header (st
);
929 st
->stat
.st_size
= realsize
;
934 pax_dump_header_0 (struct tar_sparse_file
*file
)
936 off_t block_ordinal
= current_block_ordinal ();
939 char nbuf
[UINTMAX_STRSIZE_BOUND
];
940 struct sp_array
*map
= file
->stat_info
->sparse_map
;
941 char *save_file_name
= NULL
;
943 /* Store the real file size */
944 xheader_store ("GNU.sparse.size", file
->stat_info
, NULL
);
945 xheader_store ("GNU.sparse.numblocks", file
->stat_info
, NULL
);
947 if (xheader_keyword_deleted_p ("GNU.sparse.map")
948 || tar_sparse_minor
== 0)
950 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
952 xheader_store ("GNU.sparse.offset", file
->stat_info
, &i
);
953 xheader_store ("GNU.sparse.numbytes", file
->stat_info
, &i
);
958 xheader_store ("GNU.sparse.name", file
->stat_info
, NULL
);
959 save_file_name
= file
->stat_info
->file_name
;
960 file
->stat_info
->file_name
= xheader_format_name (file
->stat_info
,
961 "%d/GNUSparseFile.%p/%f", 0);
963 xheader_string_begin (&file
->stat_info
->xhdr
);
964 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
967 xheader_string_add (&file
->stat_info
->xhdr
, ",");
968 xheader_string_add (&file
->stat_info
->xhdr
,
969 umaxtostr (map
[i
].offset
, nbuf
));
970 xheader_string_add (&file
->stat_info
->xhdr
, ",");
971 xheader_string_add (&file
->stat_info
->xhdr
,
972 umaxtostr (map
[i
].numbytes
, nbuf
));
974 if (!xheader_string_end (&file
->stat_info
->xhdr
,
977 free (file
->stat_info
->file_name
);
978 file
->stat_info
->file_name
= save_file_name
;
982 blk
= pax_start_header (file
->stat_info
);
983 finish_header (file
->stat_info
, blk
, block_ordinal
);
986 free (file
->stat_info
->file_name
);
987 file
->stat_info
->file_name
= save_file_name
;
993 pax_dump_header_1 (struct tar_sparse_file
*file
)
995 off_t block_ordinal
= current_block_ordinal ();
999 char nbuf
[UINTMAX_STRSIZE_BOUND
];
1001 struct sp_array
*map
= file
->stat_info
->sparse_map
;
1002 char *save_file_name
= file
->stat_info
->file_name
;
1004 #define COPY_STRING(b,dst,src) do \
1006 char *endp = b->buffer + BLOCKSIZE; \
1007 char const *srcp = src; \
1012 set_next_block_after (b); \
1013 b = find_next_block (); \
1015 endp = b->buffer + BLOCKSIZE; \
1021 /* Compute stored file size */
1022 p
= umaxtostr (file
->stat_info
->sparse_map_avail
, nbuf
);
1023 size
+= strlen (p
) + 1;
1024 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
1026 p
= umaxtostr (map
[i
].offset
, nbuf
);
1027 size
+= strlen (p
) + 1;
1028 p
= umaxtostr (map
[i
].numbytes
, nbuf
);
1029 size
+= strlen (p
) + 1;
1031 size
= (size
+ BLOCKSIZE
- 1) / BLOCKSIZE
;
1032 file
->stat_info
->archive_file_size
+= size
* BLOCKSIZE
;
1033 file
->dumped_size
+= size
* BLOCKSIZE
;
1035 /* Store sparse file identification */
1036 xheader_store ("GNU.sparse.major", file
->stat_info
, NULL
);
1037 xheader_store ("GNU.sparse.minor", file
->stat_info
, NULL
);
1038 xheader_store ("GNU.sparse.name", file
->stat_info
, NULL
);
1039 xheader_store ("GNU.sparse.realsize", file
->stat_info
, NULL
);
1041 file
->stat_info
->file_name
=
1042 xheader_format_name (file
->stat_info
, "%d/GNUSparseFile.%p/%f", 0);
1043 /* Make sure the created header name is shorter than NAME_FIELD_SIZE: */
1044 if (strlen (file
->stat_info
->file_name
) > NAME_FIELD_SIZE
)
1045 file
->stat_info
->file_name
[NAME_FIELD_SIZE
] = 0;
1047 blk
= pax_start_header (file
->stat_info
);
1048 finish_header (file
->stat_info
, blk
, block_ordinal
);
1049 free (file
->stat_info
->file_name
);
1050 file
->stat_info
->file_name
= save_file_name
;
1052 blk
= find_next_block ();
1054 p
= umaxtostr (file
->stat_info
->sparse_map_avail
, nbuf
);
1055 COPY_STRING (blk
, q
, p
);
1056 COPY_STRING (blk
, q
, "\n");
1057 for (i
= 0; i
< file
->stat_info
->sparse_map_avail
; i
++)
1059 p
= umaxtostr (map
[i
].offset
, nbuf
);
1060 COPY_STRING (blk
, q
, p
);
1061 COPY_STRING (blk
, q
, "\n");
1062 p
= umaxtostr (map
[i
].numbytes
, nbuf
);
1063 COPY_STRING (blk
, q
, p
);
1064 COPY_STRING (blk
, q
, "\n");
1066 memset (q
, 0, BLOCKSIZE
- (q
- blk
->buffer
));
1067 set_next_block_after (blk
);
1072 pax_dump_header (struct tar_sparse_file
*file
)
1074 file
->stat_info
->sparse_major
= tar_sparse_major
;
1075 file
->stat_info
->sparse_minor
= tar_sparse_minor
;
1077 return (file
->stat_info
->sparse_major
== 0) ?
1078 pax_dump_header_0 (file
) : pax_dump_header_1 (file
);
1082 decode_num (uintmax_t *num
, char const *arg
, uintmax_t maxval
)
1087 if (!ISDIGIT (*arg
))
1091 u
= strtoumax (arg
, &arg_lim
, 10);
1093 if (! (u
<= maxval
&& errno
!= ERANGE
) || *arg_lim
)
1101 pax_decode_header (struct tar_sparse_file
*file
)
1103 if (file
->stat_info
->sparse_major
> 0)
1106 char nbuf
[UINTMAX_STRSIZE_BOUND
];
1111 #define COPY_BUF(b,buf,src) do \
1113 char *endp = b->buffer + BLOCKSIZE; \
1117 if (dst == buf + UINTMAX_STRSIZE_BOUND -1) \
1119 ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \
1120 file->stat_info->orig_file_name)); \
1125 set_next_block_after (b); \
1126 file->dumped_size += BLOCKSIZE; \
1127 b = find_next_block (); \
1129 endp = b->buffer + BLOCKSIZE; \
1133 while (*dst++ != '\n'); \
1137 set_next_block_after (current_header
);
1138 file
->dumped_size
+= BLOCKSIZE
;
1139 blk
= find_next_block ();
1141 COPY_BUF (blk
,nbuf
,p
);
1142 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (size_t)))
1144 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1145 file
->stat_info
->orig_file_name
));
1148 file
->stat_info
->sparse_map_size
= u
;
1149 file
->stat_info
->sparse_map
= xcalloc (file
->stat_info
->sparse_map_size
,
1150 sizeof (*file
->stat_info
->sparse_map
));
1151 file
->stat_info
->sparse_map_avail
= 0;
1152 for (i
= 0; i
< file
->stat_info
->sparse_map_size
; i
++)
1156 COPY_BUF (blk
,nbuf
,p
);
1157 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (off_t
)))
1159 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1160 file
->stat_info
->orig_file_name
));
1164 COPY_BUF (blk
,nbuf
,p
);
1165 if (!decode_num (&u
, nbuf
, TYPE_MAXIMUM (off_t
)))
1167 ERROR ((0, 0, _("%s: malformed sparse archive member"),
1168 file
->stat_info
->orig_file_name
));
1172 sparse_add_map (file
->stat_info
, &sp
);
1174 set_next_block_after (blk
);
1180 static struct tar_sparse_optab
const pax_optab
= {
1181 NULL
, /* No init function */
1182 NULL
, /* No done function */
1183 pax_sparse_member_p
,
1187 NULL
, /* No scan_block function */
1189 sparse_extract_region
,