diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-06-30 18:55:00 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-06-30 18:58:40 +0200 | 
| commit | 0c23ed54144b1d41d9c0acde1b2404f7ac846e96 (patch) | |
| tree | 00b8aa6666402297b0672a972a62e4d18cb35901 /lib/tar | |
| parent | 55568b1437f4cc6634c8a6e10c96bb26256176d2 (diff) | |
Add support for gnu pax sparse file format 0.0
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/tar')
| -rw-r--r-- | lib/tar/read_header.c | 45 | 
1 files changed, 33 insertions, 12 deletions
| diff --git a/lib/tar/read_header.c b/lib/tar/read_header.c index 21642d9..23c23c4 100644 --- a/lib/tar/read_header.c +++ b/lib/tar/read_header.c @@ -19,8 +19,20 @@ enum {  	PAX_ATIME = 0x080,  	PAX_MTIME = 0x100,  	PAX_CTIME = 0x200, +	PAX_SPARSE_SIZE = 0x400,  }; +static void free_sparse_list(sparse_map_t *sparse) +{ +	sparse_map_t *old; + +	while (sparse != NULL) { +		old = sparse; +		sparse = sparse->next; +		free(old); +	} +} +  static int read_octal(const char *str, int digits, uint64_t *out)  {  	uint64_t result = 0; @@ -154,8 +166,9 @@ static int pax_read_decimal(const char *str, uint64_t *out)  static int read_pax_header(int fd, uint64_t entsize, unsigned int *set_by_pax,  			   tar_header_decoded_t *out)  { +	sparse_map_t *sparse_last = NULL, *sparse; +	uint64_t field, offset = 0, num_bytes = 0;  	char *buffer, *line; -	uint64_t field;  	ssize_t ret;  	uint64_t i; @@ -241,6 +254,25 @@ static int read_pax_header(int fd, uint64_t entsize, unsigned int *set_by_pax,  				out->sb.st_ctime = field;  			}  			*set_by_pax |= PAX_CTIME; +		} else if (!strncmp(line, "GNU.sparse.size=", 16)) { +			pax_read_decimal(line + 16, &out->actual_size); +			*set_by_pax |= PAX_SPARSE_SIZE; +		} else if (!strncmp(line, "GNU.sparse.offset=", 18)) { +			pax_read_decimal(line + 18, &offset); +		} else if (!strncmp(line, "GNU.sparse.numbytes=", 20)) { +			pax_read_decimal(line + 20, &num_bytes); +			sparse = calloc(1, sizeof(*sparse)); +			if (sparse == NULL) +				goto fail_errno; +			sparse->offset = offset; +			sparse->count = num_bytes; +			if (sparse_last == NULL) { +				free_sparse_list(out->sparse); +				out->sparse = sparse_last = sparse; +			} else { +				sparse_last->next = sparse; +				sparse_last = sparse; +			}  		}  	} @@ -449,17 +481,6 @@ fail:  	return NULL;  } -static void free_sparse_list(sparse_map_t *sparse) -{ -	sparse_map_t *old; - -	while (sparse != NULL) { -		old = sparse; -		sparse = sparse->next; -		free(old); -	} -} -  static sparse_map_t *read_gnu_old_sparse(int fd, tar_header_t *hdr)  {  	sparse_map_t *list = NULL, *end = NULL, *node; | 
