aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fstree.h11
-rw-r--r--lib/fstree/mknode.c2
-rw-r--r--lib/sqfs/data_reader.c3
-rw-r--r--lib/sqfs/data_writer.c21
-rw-r--r--lib/sqfs/tree_node_from_inode.c2
-rw-r--r--lib/sqfs/write_inode.c2
6 files changed, 23 insertions, 18 deletions
diff --git a/include/fstree.h b/include/fstree.h
index 23634fc..687b693 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -22,6 +22,14 @@ typedef struct dir_info_t dir_info_t;
typedef struct fstree_t fstree_t;
typedef struct tree_xattr_t tree_xattr_t;
+enum {
+ FILE_FLAG_HAS_FRAGMENT = 0x01,
+
+ FILE_FLAG_FRAGMENT_IS_DUPLICATE = 0x02,
+
+ FILE_FLAG_BLOCKS_ARE_DUPLICATE = 0x04,
+};
+
/* Encapsulates a set of key-value pairs attached to a tree_node_t */
struct tree_xattr_t {
/* Number of key-value pairs */
@@ -80,6 +88,9 @@ struct file_info_t {
uint32_t fragment_chksum;
+ /* combination of FILE_FLAG_* flags */
+ uint32_t flags;
+
/* Stores data about each full data block. */
struct {
uint32_t chksum;
diff --git a/lib/fstree/mknode.c b/lib/fstree/mknode.c
index 18602e4..d343145 100644
--- a/lib/fstree/mknode.c
+++ b/lib/fstree/mknode.c
@@ -60,8 +60,6 @@ tree_node_t *fstree_mknode(fstree_t *fs, tree_node_t *parent, const char *name,
case S_IFREG:
n->data.file = (file_info_t *)n->payload;
n->data.file->size = sb->st_size;
- n->data.file->fragment = 0xFFFFFFFF;
- n->data.file->fragment_offset = 0xFFFFFFFF;
if (extra == NULL)
break;
diff --git a/lib/sqfs/data_reader.c b/lib/sqfs/data_reader.c
index 5facaa1..a7d605e 100644
--- a/lib/sqfs/data_reader.c
+++ b/lib/sqfs/data_reader.c
@@ -205,8 +205,7 @@ int data_reader_dump_file(data_reader_t *data, file_info_t *fi, int outfd,
size_t fragsz = fi->size % data->block_size;
size_t count = fi->size / data->block_size;
- if (fragsz != 0 && (fi->fragment == 0xFFFFFFFF ||
- fi->fragment_offset == 0xFFFFFFFF)) {
+ if (fragsz != 0 && !(fi->flags & FILE_FLAG_HAS_FRAGMENT)) {
fragsz = 0;
++count;
}
diff --git a/lib/sqfs/data_writer.c b/lib/sqfs/data_writer.c
index 496d636..e9a6193 100644
--- a/lib/sqfs/data_writer.c
+++ b/lib/sqfs/data_writer.c
@@ -138,10 +138,10 @@ static file_info_t *fragment_by_chksum(file_info_t *fi, uint32_t chksum,
break;
}
- if (it->fragment == 0xFFFFFFFF)
+ if (!(it->flags & FILE_FLAG_HAS_FRAGMENT))
continue;
- if (it->fragment_offset == 0xFFFFFFFF)
+ if (it->flags & FILE_FLAG_FRAGMENT_IS_DUPLICATE)
continue;
if ((it->size % block_size) != frag_size)
@@ -158,11 +158,8 @@ static size_t get_block_count(file_info_t *fi, size_t block_size)
{
size_t count = fi->size / block_size;
- if ((fi->size % block_size != 0) &&
- (fi->fragment == 0xFFFFFFFF ||
- fi->fragment_offset == 0xFFFFFFFF)) {
+ if ((fi->size % block_size) && !(fi->flags & FILE_FLAG_HAS_FRAGMENT))
++count;
- }
while (count > 0 && fi->blocks[count - 1].size == 0)
--count;
@@ -201,21 +198,15 @@ static uint64_t find_equal_blocks(file_info_t *file, file_info_t *list,
break;
}
- location = 0;
-
for (it = list; it != NULL; it = it->next) {
if (it == file) {
it = NULL;
break;
}
- /* XXX: list assumed to be processed in order, prevent us from
- re-checking files we know are duplicates */
- if (it->startblock < location)
+ if (it->flags & FILE_FLAG_BLOCKS_ARE_DUPLICATE)
continue;
- location = it->startblock;
-
cmp_blk_count = get_block_count(it, block_size);
if (cmp_blk_count == 0)
continue;
@@ -279,6 +270,8 @@ static int flush_data_block(data_writer_t *data, size_t size,
chksum = update_crc32(0, data->block, size);
if (size < data->super->block_size && !(flags & DW_DONT_FRAGMENT)) {
+ fi->flags |= FILE_FLAG_HAS_FRAGMENT;
+
ref = fragment_by_chksum(fi, chksum, size, list,
data->super->block_size);
@@ -286,6 +279,7 @@ static int flush_data_block(data_writer_t *data, size_t size,
fi->fragment_chksum = ref->fragment_chksum;
fi->fragment_offset = ref->fragment_offset;
fi->fragment = ref->fragment;
+ fi->flags |= FILE_FLAG_FRAGMENT_IS_DUPLICATE;
return 0;
}
@@ -344,6 +338,7 @@ static int end_file(data_writer_t *data, file_info_t *fi,
if (ref > 0) {
fi->startblock = ref;
+ fi->flags |= FILE_FLAG_BLOCKS_ARE_DUPLICATE;
if (lseek(data->outfd, start, SEEK_SET) == (off_t)-1)
goto fail_seek;
diff --git a/lib/sqfs/tree_node_from_inode.c b/lib/sqfs/tree_node_from_inode.c
index 034218c..84ebbb2 100644
--- a/lib/sqfs/tree_node_from_inode.c
+++ b/lib/sqfs/tree_node_from_inode.c
@@ -50,6 +50,8 @@ static void copy_block_sizes(sqfs_inode_generic_t *inode, tree_node_t *out,
if (out->data.file->fragment == 0xFFFFFFFF ||
out->data.file->fragment_offset == 0xFFFFFFFF) {
++block_count;
+ } else {
+ out->data.file->flags |= FILE_FLAG_HAS_FRAGMENT;
}
}
diff --git a/lib/sqfs/write_inode.c b/lib/sqfs/write_inode.c
index 726206e..efb6a7d 100644
--- a/lib/sqfs/write_inode.c
+++ b/lib/sqfs/write_inode.c
@@ -83,7 +83,7 @@ static int write_file_blocks(fstree_t *fs, file_info_t *fi, meta_writer_t *im)
uint32_t bs;
if ((fi->size % fs->block_size) != 0 &&
- (fi->fragment == 0xFFFFFFFF || fi->fragment_offset == 0xFFFFFFFF)) {
+ !(fi->flags & FILE_FLAG_HAS_FRAGMENT)) {
++count;
}