summaryrefslogtreecommitdiff
path: root/lib/sqfs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs')
-rw-r--r--lib/sqfs/data_writer.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/lib/sqfs/data_writer.c b/lib/sqfs/data_writer.c
index 557b85b..cbe2351 100644
--- a/lib/sqfs/data_writer.c
+++ b/lib/sqfs/data_writer.c
@@ -18,6 +18,8 @@ struct data_writer_t {
size_t max_fragments;
size_t frag_offset;
+ size_t devblksz;
+
int block_idx;
sqfs_super_t *super;
@@ -26,14 +28,16 @@ struct data_writer_t {
};
static int write_compressed(data_writer_t *data, const void *in, size_t size,
- uint32_t *outsize)
+ uint32_t *outsize, int flags)
{
- ssize_t ret;
+ ssize_t ret = 0;
- ret = data->cmp->do_block(data->cmp, in, size, data->scratch,
- data->super->block_size);
- if (ret < 0)
- return -1;
+ if (!(flags & DW_DONT_COMPRESS)) {
+ 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;
@@ -85,6 +89,20 @@ static bool is_zero_block(unsigned char *ptr, size_t size)
return ptr[0] == 0 && memcmp(ptr, ptr + 1, size - 1) == 0;
}
+static int allign_file(data_writer_t *data)
+{
+ size_t diff = data->super->bytes_used % data->devblksz;
+
+ if (diff == 0)
+ return 0;
+
+ if (padd_file(data->outfd, data->super->bytes_used, data->devblksz))
+ return -1;
+
+ data->super->bytes_used += data->devblksz - diff;
+ return 0;
+}
+
int data_writer_flush_fragments(data_writer_t *data)
{
uint64_t offset;
@@ -98,7 +116,7 @@ int data_writer_flush_fragments(data_writer_t *data)
offset = data->super->bytes_used;
- if (write_compressed(data, data->fragment, data->frag_offset, &out))
+ if (write_compressed(data, data->fragment, data->frag_offset, &out, 0))
return -1;
data->fragments[data->num_fragments].start_offset = htole64(offset);
@@ -113,7 +131,8 @@ int data_writer_flush_fragments(data_writer_t *data)
return 0;
}
-static int flush_data_block(data_writer_t *data, size_t size, file_info_t *fi)
+static int flush_data_block(data_writer_t *data, size_t size,
+ file_info_t *fi, int flags)
{
uint32_t out;
@@ -123,7 +142,7 @@ static int flush_data_block(data_writer_t *data, size_t size, file_info_t *fi)
return 0;
}
- if (size < data->super->block_size) {
+ if (size < data->super->block_size && !(flags & DW_DONT_FRAGMENT)) {
if (data->frag_offset + size > data->super->block_size) {
if (data_writer_flush_fragments(data))
return -1;
@@ -136,7 +155,7 @@ static int flush_data_block(data_writer_t *data, size_t size, file_info_t *fi)
data->block, size);
data->frag_offset += size;
} else {
- if (write_compressed(data, data->block, size, &out))
+ if (write_compressed(data, data->block, size, &out, flags))
return -1;
fi->blocksizes[data->block_idx++] = out;
@@ -145,12 +164,16 @@ static int flush_data_block(data_writer_t *data, size_t size, file_info_t *fi)
return 0;
}
-int write_data_from_fd(data_writer_t *data, file_info_t *fi, int infd)
+int write_data_from_fd(data_writer_t *data, file_info_t *fi,
+ int infd, int flags)
{
uint64_t count;
ssize_t ret;
size_t diff;
+ if ((flags & DW_ALLIGN_DEVBLK) && allign_file(data) != 0)
+ return -1;
+
fi->startblock = data->super->bytes_used;
fi->sparse = 0;
data->block_idx = 0;
@@ -165,10 +188,13 @@ int write_data_from_fd(data_writer_t *data, file_info_t *fi, int infd)
if ((size_t)ret < diff)
goto fail_trunc;
- if (flush_data_block(data, diff, fi))
+ if (flush_data_block(data, diff, fi, flags))
return -1;
}
+ if ((flags & DW_ALLIGN_DEVBLK) && allign_file(data) != 0)
+ return -1;
+
return 0;
fail_read:
perror(fi->input_file);
@@ -179,13 +205,16 @@ fail_trunc:
}
int write_data_from_fd_condensed(data_writer_t *data, file_info_t *fi,
- int infd, sparse_map_t *map)
+ int infd, sparse_map_t *map, int flags)
{
size_t start, count, diff;
sparse_map_t *m;
uint64_t offset;
ssize_t ret;
+ if ((flags & DW_ALLIGN_DEVBLK) && allign_file(data) != 0)
+ return -1;
+
fi->startblock = data->super->bytes_used;
fi->sparse = 0;
data->block_idx = 0;
@@ -235,10 +264,13 @@ int write_data_from_fd_condensed(data_writer_t *data, file_info_t *fi,
map = map->next;
}
- if (flush_data_block(data, diff, fi))
+ if (flush_data_block(data, diff, fi, flags))
return -1;
}
+ if ((flags & DW_ALLIGN_DEVBLK) && allign_file(data) != 0)
+ return -1;
+
return 0;
fail_map_size:
fprintf(stderr, "%s: sparse file map spans beyond file size\n",
@@ -258,7 +290,7 @@ fail_trunc:
}
data_writer_t *data_writer_create(sqfs_super_t *super, compressor_t *cmp,
- int outfd)
+ int outfd, size_t devblksize)
{
data_writer_t *data;
@@ -275,6 +307,7 @@ data_writer_t *data_writer_create(sqfs_super_t *super, compressor_t *cmp,
data->super = super;
data->cmp = cmp;
data->outfd = outfd;
+ data->devblksz = devblksize;
return data;
}