libsparse: add a function to retrieve the data blocks

Test: m libsparse

Change-Id: I04bd3912bb4364e591b064ec2aab782cf02f6bd7
This commit is contained in:
Adrien Schildknecht 2016-11-30 11:49:47 -08:00
parent 59826ddee5
commit a26a6bd6f3
2 changed files with 81 additions and 0 deletions

View File

@ -175,6 +175,13 @@ int sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse,
*/
int64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc);
/**
* sparse_file_block_size
*
* @s - sparse file cookie
*/
unsigned int sparse_file_block_size(struct sparse_file *s);
/**
* sparse_file_callback - call a callback for blocks in sparse file
*
@ -196,6 +203,24 @@ int64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc);
int sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
int (*write)(void *priv, const void *data, int len), void *priv);
/**
* sparse_file_foreach_chunk - call a callback for data blocks in sparse file
*
* @s - sparse file cookie
* @sparse - write in the Android sparse file format
* @crc - append a crc chunk
* @write - function to call for each block
* @priv - value that will be passed as the first argument to write
*
* The function has the same behavior as 'sparse_file_callback', except it only
* iterates on blocks that contain data.
*
* Returns 0 on success, negative errno on error.
*/
int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
int (*write)(void *priv, const void *data, int len, unsigned int block,
unsigned int nr_blocks),
void *priv);
/**
* sparse_file_read - read a file into a sparse file cookie
*

View File

@ -199,6 +199,57 @@ int sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
return ret;
}
struct chunk_data {
void *priv;
unsigned int block;
unsigned int nr_blocks;
int (*write)(void *priv, const void *data, int len, unsigned int block,
unsigned int nr_blocks);
};
static int foreach_chunk_write(void *priv, const void *data, int len)
{
struct chunk_data *chk = priv;
return chk->write(chk->priv, data, len, chk->block, chk->nr_blocks);
}
int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
int (*write)(void *priv, const void *data, int len, unsigned int block,
unsigned int nr_blocks),
void *priv)
{
int ret;
int chunks;
struct chunk_data chk;
struct output_file *out;
struct backed_block *bb;
chk.priv = priv;
chk.write = write;
chk.block = chk.nr_blocks = 0;
chunks = sparse_count_chunks(s);
out = output_file_open_callback(foreach_chunk_write, &chk,
s->block_size, s->len, false, sparse,
chunks, crc);
if (!out)
return -ENOMEM;
for (bb = backed_block_iter_new(s->backed_block_list); bb;
bb = backed_block_iter_next(bb)) {
chk.block = backed_block_block(bb);
chk.nr_blocks = (backed_block_len(bb) - 1) / s->block_size + 1;
ret = sparse_file_write_block(out, bb);
if (ret)
return ret;
}
output_file_close(out);
return ret;
}
static int out_counter_write(void *priv, const void *data __unused, int len)
{
int64_t *count = priv;
@ -230,6 +281,11 @@ int64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc)
return count;
}
unsigned int sparse_file_block_size(struct sparse_file *s)
{
return s->block_size;
}
static struct backed_block *move_chunks_up_to_len(struct sparse_file *from,
struct sparse_file *to, unsigned int len)
{