aboutsummaryrefslogtreecommitdiff
path: root/mkfs/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'mkfs/block.c')
-rw-r--r--mkfs/block.c183
1 files changed, 105 insertions, 78 deletions
diff --git a/mkfs/block.c b/mkfs/block.c
index 896cefc..4bc9684 100644
--- a/mkfs/block.c
+++ b/mkfs/block.c
@@ -2,22 +2,37 @@
#include "mkfs.h"
#include "util.h"
-static int write_compressed(sqfs_info_t *info, const void *in, size_t size,
+struct data_writer_t {
+ void *block;
+ void *fragment;
+ void *scratch;
+
+ sqfs_fragment_t *fragments;
+ size_t num_fragments;
+ size_t max_fragments;
+ size_t frag_offset;
+
+ sqfs_super_t *super;
+ compressor_t *cmp;
+ int outfd;
+};
+
+static int write_compressed(data_writer_t *data, const void *in, size_t size,
uint32_t *outsize)
{
ssize_t ret;
- ret = info->cmp->do_block(info->cmp, in, size, info->scratch,
- info->super.block_size);
+ ret = data->cmp->do_block(data->cmp, in, size, data->scratch,
+ data->super->block_size);
if (ret < 0)
return -1;
if (ret > 0 && (size_t)ret < size) {
size = ret;
- ret = write_retry(info->outfd, info->scratch, size);
+ ret = write_retry(data->outfd, data->scratch, size);
*outsize = size;
} else {
- ret = write_retry(info->outfd, in, size);
+ ret = write_retry(data->outfd, in, size);
*outsize = size | (1 << 24);
}
@@ -31,58 +46,58 @@ static int write_compressed(sqfs_info_t *info, const void *in, size_t size,
return -1;
}
- info->super.bytes_used += ret;
+ data->super->bytes_used += ret;
return 0;
}
-static int grow_fragment_table(sqfs_info_t *info)
+static int grow_fragment_table(data_writer_t *data)
{
size_t newsz;
void *new;
- if (info->num_fragments == info->max_fragments) {
- newsz = info->max_fragments ? info->max_fragments * 2 : 16;
- new = realloc(info->fragments,
- sizeof(info->fragments[0]) * newsz);
+ if (data->num_fragments == data->max_fragments) {
+ newsz = data->max_fragments ? data->max_fragments * 2 : 16;
+ new = realloc(data->fragments,
+ sizeof(data->fragments[0]) * newsz);
if (new == NULL) {
perror("appending to fragment table");
return -1;
}
- info->max_fragments = newsz;
- info->fragments = new;
+ data->max_fragments = newsz;
+ data->fragments = new;
}
return 0;
}
-static int flush_fragments(sqfs_info_t *info)
+int data_writer_flush_fragments(data_writer_t *data)
{
uint64_t offset;
uint32_t out;
- if (grow_fragment_table(info))
+ if (grow_fragment_table(data))
return -1;
- offset = info->super.bytes_used;
+ offset = data->super->bytes_used;
- if (write_compressed(info, info->fragment, info->frag_offset, &out))
+ if (write_compressed(data, data->fragment, data->frag_offset, &out))
return -1;
- info->fragments[info->num_fragments].start_offset = htole64(offset);
- info->fragments[info->num_fragments].pad0 = 0;
- info->fragments[info->num_fragments].size = htole32(out);
+ data->fragments[data->num_fragments].start_offset = htole64(offset);
+ data->fragments[data->num_fragments].pad0 = 0;
+ data->fragments[data->num_fragments].size = htole32(out);
- info->num_fragments += 1;
- info->frag_offset = 0;
+ data->num_fragments += 1;
+ data->frag_offset = 0;
- info->super.flags &= ~SQFS_FLAG_NO_FRAGMENTS;
- info->super.flags |= SQFS_FLAG_ALWAYS_FRAGMENTS;
+ data->super->flags &= ~SQFS_FLAG_NO_FRAGMENTS;
+ data->super->flags |= SQFS_FLAG_ALWAYS_FRAGMENTS;
return 0;
}
-static int write_data_from_fd(sqfs_info_t *info, file_info_t *fi, int infd)
+int write_data_from_fd(data_writer_t *data, file_info_t *fi, int infd)
{
uint64_t count = fi->size;
int blk_idx = 0;
@@ -90,33 +105,33 @@ static int write_data_from_fd(sqfs_info_t *info, file_info_t *fi, int infd)
ssize_t ret;
size_t diff;
- fi->startblock = info->super.bytes_used;
+ fi->startblock = data->super->bytes_used;
while (count != 0) {
- diff = count > (uint64_t)info->super.block_size ?
- info->super.block_size : count;
+ diff = count > (uint64_t)data->super->block_size ?
+ data->super->block_size : count;
- ret = read_retry(infd, info->block, diff);
+ ret = read_retry(infd, data->block, diff);
if (ret < 0)
goto fail_read;
if ((size_t)ret < diff)
goto fail_trunc;
- if (diff < info->super.block_size) {
- if (info->frag_offset + diff > info->super.block_size) {
- if (flush_fragments(info))
+ if (diff < data->super->block_size) {
+ if (data->frag_offset + diff > data->super->block_size) {
+ if (data_writer_flush_fragments(data))
return -1;
}
- fi->fragment_offset = info->frag_offset;
- fi->fragment = info->num_fragments;
+ fi->fragment_offset = data->frag_offset;
+ fi->fragment = data->num_fragments;
- memcpy((char *)info->fragment + info->frag_offset,
- info->block, diff);
- info->frag_offset += diff;
+ memcpy((char *)data->fragment + data->frag_offset,
+ data->block, diff);
+ data->frag_offset += diff;
} else {
- if (write_compressed(info, info->block,
- info->super.block_size, &out)) {
+ if (write_compressed(data, data->block,
+ data->super->block_size, &out)) {
return -1;
}
@@ -135,7 +150,50 @@ fail_trunc:
return -1;
}
-static int process_file(sqfs_info_t *info, file_info_t *fi)
+data_writer_t *data_writer_create(sqfs_super_t *super, compressor_t *cmp,
+ int outfd)
+{
+ data_writer_t *data;
+
+ data = calloc(1, sizeof(*data) + super->block_size * 3);
+ if (data == NULL) {
+ perror("creating data writer");
+ return NULL;
+ }
+
+ data->block = (char *)data + sizeof(*data);
+ data->fragment = (char *)data->block + super->block_size;
+ data->scratch = (char *)data->fragment + super->block_size;
+
+ data->super = super;
+ data->cmp = cmp;
+ data->outfd = outfd;
+ return data;
+}
+
+void data_writer_destroy(data_writer_t *data)
+{
+ free(data->fragments);
+ free(data);
+}
+
+int data_writer_write_fragment_table(data_writer_t *data)
+{
+ uint64_t start;
+
+ data->super->fragment_entry_count = data->num_fragments;
+
+ if (sqfs_write_table(data->outfd, data->super, data->fragments,
+ sizeof(data->fragments[0]), data->num_fragments,
+ &start, data->cmp)) {
+ return -1;
+ }
+
+ data->super->fragment_table_start = start;
+ return 0;
+}
+
+static int process_file(data_writer_t *data, file_info_t *fi)
{
int ret, infd;
@@ -145,7 +203,7 @@ static int process_file(sqfs_info_t *info, file_info_t *fi)
return -1;
}
- ret = write_data_from_fd(info, fi, infd);
+ ret = write_data_from_fd(data, fi, infd);
close(infd);
return ret;
@@ -161,12 +219,12 @@ static void print_name(tree_node_t *n)
fputs(n->name, stdout);
}
-static int find_and_process_files(sqfs_info_t *info, tree_node_t *n,
+static int find_and_process_files(data_writer_t *data, tree_node_t *n,
bool quiet)
{
if (S_ISDIR(n->mode)) {
for (n = n->data.dir->children; n != NULL; n = n->next) {
- if (find_and_process_files(info, n, quiet))
+ if (find_and_process_files(data, n, quiet))
return -1;
}
return 0;
@@ -179,13 +237,13 @@ static int find_and_process_files(sqfs_info_t *info, tree_node_t *n,
fputc('\n', stdout);
}
- return process_file(info, n->data.file);
+ return process_file(data, n->data.file);
}
return 0;
}
-int write_data_to_image(sqfs_info_t *info)
+int write_data_to_image(data_writer_t *data, sqfs_info_t *info)
{
bool need_restore = false;
const char *ptr;
@@ -206,40 +264,9 @@ int write_data_to_image(sqfs_info_t *info)
}
}
- info->block = malloc(info->super.block_size);
-
- if (info->block == NULL) {
- perror("allocating data block buffer");
- return -1;
- }
-
- info->fragment = malloc(info->super.block_size);
-
- if (info->fragment == NULL) {
- perror("allocating fragment buffer");
- free(info->block);
- return -1;
- }
-
- info->scratch = malloc(info->super.block_size);
- if (info->scratch == NULL) {
- perror("allocating scratch buffer");
- free(info->block);
- free(info->fragment);
- return -1;
- }
-
- ret = find_and_process_files(info, info->fs.root, info->opt.quiet);
-
- ret = ret == 0 ? flush_fragments(info) : ret;
-
- free(info->block);
- free(info->fragment);
- free(info->scratch);
+ ret = find_and_process_files(data, info->fs.root, info->opt.quiet);
- info->block = NULL;
- info->fragment = NULL;
- info->scratch = NULL;
+ ret = ret == 0 ? data_writer_flush_fragments(data) : ret;
if (need_restore)
ret = popd();