summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--difftool/compare_dir.c26
-rw-r--r--difftool/compare_files.c30
-rw-r--r--difftool/extract.c19
-rw-r--r--difftool/node_compare.c56
-rw-r--r--difftool/sqfsdiff.c104
-rw-r--r--difftool/sqfsdiff.h29
-rw-r--r--difftool/util.c7
-rw-r--r--include/data_reader.h16
-rw-r--r--lib/sqfshelper/data_reader.c155
9 files changed, 260 insertions, 182 deletions
diff --git a/difftool/compare_dir.c b/difftool/compare_dir.c
index 99a0a37..477346a 100644
--- a/difftool/compare_dir.c
+++ b/difftool/compare_dir.c
@@ -6,16 +6,18 @@
*/
#include "sqfsdiff.h"
-int compare_dir_entries(sqfsdiff_t *sd, tree_node_t *old, tree_node_t *new)
+int compare_dir_entries(sqfsdiff_t *sd, sqfs_tree_node_t *old,
+ sqfs_tree_node_t *new)
{
- tree_node_t *old_it = old->data.dir->children, *old_prev = NULL;
- tree_node_t *new_it = new->data.dir->children, *new_prev = NULL;
+ sqfs_tree_node_t *old_it = old->children, *old_prev = NULL;
+ sqfs_tree_node_t *new_it = new->children, *new_prev = NULL;
int ret, result = 0;
char *path;
while (old_it != NULL || new_it != NULL) {
if (old_it != NULL && new_it != NULL) {
- ret = strcmp(old_it->name, new_it->name);
+ ret = strcmp((const char *)old_it->name,
+ (const char *)new_it->name);
} else if (old_it == NULL) {
ret = 1;
} else {
@@ -29,8 +31,8 @@ int compare_dir_entries(sqfsdiff_t *sd, tree_node_t *old, tree_node_t *new)
return -1;
if ((sd->compare_flags & COMPARE_EXTRACT_FILES) &&
- S_ISREG(old_it->mode)) {
- if (extract_files(sd, old_it->data.file,
+ S_ISREG(old_it->inode->base.mode)) {
+ if (extract_files(sd, old_it->inode,
NULL, path)) {
free(path);
return -1;
@@ -41,9 +43,9 @@ int compare_dir_entries(sqfsdiff_t *sd, tree_node_t *old, tree_node_t *new)
free(path);
if (old_prev == NULL) {
- old->data.dir->children = old_it->next;
+ old->children = old_it->next;
free(old_it);
- old_it = old->data.dir->children;
+ old_it = old->children;
} else {
old_prev->next = old_it->next;
free(old_it);
@@ -56,8 +58,8 @@ int compare_dir_entries(sqfsdiff_t *sd, tree_node_t *old, tree_node_t *new)
return -1;
if ((sd->compare_flags & COMPARE_EXTRACT_FILES) &&
- S_ISREG(new_it->mode)) {
- if (extract_files(sd, NULL, new_it->data.file,
+ S_ISREG(new_it->inode->base.mode)) {
+ if (extract_files(sd, NULL, new_it->inode,
path)) {
free(path);
return -1;
@@ -68,9 +70,9 @@ int compare_dir_entries(sqfsdiff_t *sd, tree_node_t *old, tree_node_t *new)
free(path);
if (new_prev == NULL) {
- new->data.dir->children = new_it->next;
+ new->children = new_it->next;
free(new_it);
- new_it = new->data.dir->children;
+ new_it = new->children;
} else {
new_prev->next = new_it->next;
free(new_it);
diff --git a/difftool/compare_files.c b/difftool/compare_files.c
index 6138569..591fc2c 100644
--- a/difftool/compare_files.c
+++ b/difftool/compare_files.c
@@ -10,12 +10,12 @@ static unsigned char old_buf[MAX_WINDOW_SIZE];
static unsigned char new_buf[MAX_WINDOW_SIZE];
static int read_blob(const char *prefix, const char *path,
- data_reader_t *rd, file_info_t *fi, void *buffer,
- off_t offset, size_t size)
+ data_reader_t *rd, const sqfs_inode_generic_t *inode,
+ void *buffer, uint64_t offset, size_t size)
{
ssize_t ret;
- ret = data_reader_read(rd, fi, offset, buffer, size);
+ ret = data_reader_read(rd, inode, offset, buffer, size);
ret = (ret < 0 || (size_t)ret < size) ? -1 : 0;
if (ret) {
@@ -27,20 +27,32 @@ static int read_blob(const char *prefix, const char *path,
return 0;
}
-int compare_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new,
- const char *path)
+int compare_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old,
+ const sqfs_inode_generic_t *new, const char *path)
{
- uint64_t offset, diff;
+ uint64_t offset, diff, oldsz, newsz;
int status = 0, ret;
- if (old->size != new->size)
+ if (old->base.type == SQFS_INODE_EXT_FILE) {
+ oldsz = old->data.file_ext.file_size;
+ } else {
+ oldsz = old->data.file.file_size;
+ }
+
+ if (new->base.type == SQFS_INODE_EXT_FILE) {
+ newsz = new->data.file_ext.file_size;
+ } else {
+ newsz = new->data.file.file_size;
+ }
+
+ if (oldsz != newsz)
goto out_different;
if (sd->compare_flags & COMPARE_NO_CONTENTS)
return 0;
- for (offset = 0; offset < old->size; offset += diff) {
- diff = old->size - offset;
+ for (offset = 0; offset < oldsz; offset += diff) {
+ diff = oldsz - offset;
if (diff > MAX_WINDOW_SIZE)
diff = MAX_WINDOW_SIZE;
diff --git a/difftool/extract.c b/difftool/extract.c
index 2e92710..45c5560 100644
--- a/difftool/extract.c
+++ b/difftool/extract.c
@@ -6,7 +6,7 @@
*/
#include "sqfsdiff.h"
-static int extract(data_reader_t *data, file_info_t *fi,
+static int extract(data_reader_t *data, const sqfs_inode_generic_t *inode,
const char *prefix, const char *path)
{
char *ptr, *temp;
@@ -27,7 +27,7 @@ static int extract(data_reader_t *data, file_info_t *fi,
return -1;
}
- if (data_reader_dump_file(data, fi, fd, true)) {
+ if (data_reader_dump(data, inode, fd, true)) {
close(fd);
return -1;
}
@@ -36,14 +36,19 @@ static int extract(data_reader_t *data, file_info_t *fi,
return 0;
}
-int extract_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new,
+int extract_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old,
+ const sqfs_inode_generic_t *new,
const char *path)
{
- if (extract(sd->sqfs_old.data, old, "old", path))
- return -1;
+ if (old != NULL) {
+ if (extract(sd->sqfs_old.data, old, "old", path))
+ return -1;
+ }
- if (extract(sd->sqfs_new.data, new, "new", path))
- return -1;
+ if (new != NULL) {
+ if (extract(sd->sqfs_new.data, new, "new", path))
+ return -1;
+ }
return 0;
}
diff --git a/difftool/node_compare.c b/difftool/node_compare.c
index 504c9cf..7638805 100644
--- a/difftool/node_compare.c
+++ b/difftool/node_compare.c
@@ -6,23 +6,24 @@
*/
#include "sqfsdiff.h"
-int node_compare(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b)
+int node_compare(sqfsdiff_t *sd, sqfs_tree_node_t *a, sqfs_tree_node_t *b)
{
- char *path = node_path(a);
- tree_node_t *ait, *bit;
+ char *path = sqfs_tree_node_get_path(a);
+ sqfs_tree_node_t *ait, *bit;
int ret, status = 0;
if (path == NULL)
return -1;
- if ((a->mode & S_IFMT) != (b->mode & S_IFMT)) {
+ if (a->inode->base.type != b->inode->base.type) {
fprintf(stdout, "%s has a different type\n", path);
free(path);
return 1;
}
if (!(sd->compare_flags & COMPARE_NO_PERM)) {
- if ((a->mode & ~S_IFMT) != (b->mode & ~S_IFMT)) {
+ if ((a->inode->base.mode & ~S_IFMT) !=
+ (b->inode->base.mode & ~S_IFMT)) {
fprintf(stdout, "%s has different permissions\n",
path);
status = 1;
@@ -37,39 +38,53 @@ int node_compare(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b)
}
if (sd->compare_flags & COMPARE_TIMESTAMP) {
- if (a->mod_time != b->mod_time) {
+ if (a->inode->base.mod_time != b->inode->base.mod_time) {
fprintf(stdout, "%s has a different timestamp\n", path);
status = 1;
}
}
if (sd->compare_flags & COMPARE_INODE_NUM) {
- if (a->inode_num != b->inode_num) {
+ if (a->inode->base.inode_number !=
+ b->inode->base.inode_number) {
fprintf(stdout, "%s has a different inode number\n",
path);
status = 1;
}
}
- switch (a->mode & S_IFMT) {
- case S_IFSOCK:
- case S_IFIFO:
+ switch (a->inode->base.type) {
+ case SQFS_INODE_SOCKET:
+ case SQFS_INODE_EXT_SOCKET:
+ case SQFS_INODE_FIFO:
+ case SQFS_INODE_EXT_FIFO:
break;
- case S_IFBLK:
- case S_IFCHR:
- if (a->data.devno != b->data.devno) {
+ case SQFS_INODE_BDEV:
+ case SQFS_INODE_CDEV:
+ if (a->inode->data.dev.devno != b->inode->data.dev.devno) {
fprintf(stdout, "%s has different device number\n",
path);
status = 1;
}
break;
- case S_IFLNK:
- if (strcmp(a->data.slink_target, b->data.slink_target) != 0) {
+ case SQFS_INODE_EXT_BDEV:
+ case SQFS_INODE_EXT_CDEV:
+ if (a->inode->data.dev_ext.devno !=
+ b->inode->data.dev_ext.devno) {
+ fprintf(stdout, "%s has different device number\n",
+ path);
+ status = 1;
+ }
+ break;
+ case SQFS_INODE_SLINK:
+ case SQFS_INODE_EXT_SLINK:
+ if (strcmp(a->inode->slink_target, b->inode->slink_target)) {
fprintf(stdout, "%s has a different link target\n",
path);
}
break;
- case S_IFDIR:
+ case SQFS_INODE_DIR:
+ case SQFS_INODE_EXT_DIR:
ret = compare_dir_entries(sd, a, b);
if (ret < 0) {
status = -1;
@@ -81,8 +96,8 @@ int node_compare(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b)
free(path);
path = NULL;
- ait = a->data.dir->children;
- bit = b->data.dir->children;
+ ait = a->children;
+ bit = b->children;
while (ait != NULL && bit != NULL) {
ret = node_compare(sd, ait, bit);
@@ -95,8 +110,9 @@ int node_compare(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b)
bit = bit->next;
}
break;
- case S_IFREG:
- ret = compare_files(sd, a->data.file, b->data.file, path);
+ case SQFS_INODE_FILE:
+ case SQFS_INODE_EXT_FILE:
+ ret = compare_files(sd, a->inode, b->inode, path);
if (ret < 0) {
status = -1;
} else if (ret > 0) {
diff --git a/difftool/sqfsdiff.c b/difftool/sqfsdiff.c
index a661223..6d1a9af 100644
--- a/difftool/sqfsdiff.c
+++ b/difftool/sqfsdiff.c
@@ -6,6 +6,100 @@
*/
#include "sqfsdiff.h"
+static int open_sfqs(sqfs_state_t *state, const char *path)
+{
+ state->file = sqfs_open_file(path, SQFS_FILE_OPEN_READ_ONLY);
+ if (state->file == NULL) {
+ perror(path);
+ return -1;
+ }
+
+ if (sqfs_super_read(&state->super, state->file)) {
+ fprintf(stderr, "error reading super block from %s\n",
+ path);
+ goto fail_file;
+ }
+
+ if (!sqfs_compressor_exists(state->super.compression_id)) {
+ fprintf(stderr, "%s: unknown compressor used.\n",
+ path);
+ goto fail_file;
+ }
+
+ sqfs_compressor_config_init(&state->cfg, state->super.compression_id,
+ state->super.block_size,
+ SQFS_COMP_FLAG_UNCOMPRESS);
+
+ state->cmp = sqfs_compressor_create(&state->cfg);
+ if (state->cmp == NULL) {
+ fprintf(stderr, "%s: error creating compressor.\n", path);
+ goto fail_file;
+ }
+
+ if (state->super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) {
+ if (state->cmp->read_options(state->cmp, state->file)) {
+ fprintf(stderr, "%s: error loading compressor "
+ "options.\n", path);
+ goto fail_cmp;
+ }
+ }
+
+ state->idtbl = sqfs_id_table_create();
+ if (state->idtbl == NULL) {
+ perror("error creating ID table");
+ goto fail_cmp;
+ }
+
+ if (sqfs_id_table_read(state->idtbl, state->file,
+ &state->super, state->cmp)) {
+ fprintf(stderr, "%s: error loading ID table\n", path);
+ goto fail_id;
+ }
+
+ state->dr = sqfs_dir_reader_create(&state->super, state->cmp,
+ state->file);
+ if (state->dr == NULL) {
+ perror("creating directory reader");
+ goto fail_dr;
+ }
+
+ if (sqfs_dir_reader_get_full_hierarchy(state->dr, state->idtbl,
+ NULL, 0, &state->root)) {
+ fprintf(stderr, "%s: error loading file system tree\n", path);
+ goto fail_dr;
+ }
+
+ state->data = data_reader_create(state->file, &state->super,
+ state->cmp);
+ if (state->data == NULL) {
+ fprintf(stderr, "%s: error loading file system tree\n", path);
+ goto fail_tree;
+ }
+
+ return 0;
+fail_tree:
+ sqfs_dir_tree_destroy(state->root);
+fail_dr:
+ sqfs_dir_reader_destroy(state->dr);
+fail_id:
+ sqfs_id_table_destroy(state->idtbl);
+fail_cmp:
+ state->cmp->destroy(state->cmp);
+fail_file:
+ state->file->destroy(state->file);
+ return -1;
+}
+
+static void close_sfqs(sqfs_state_t *state)
+{
+ data_reader_destroy(state->data);
+ sqfs_dir_tree_destroy(state->root);
+ sqfs_dir_reader_destroy(state->dr);
+ sqfs_id_table_destroy(state->idtbl);
+ state->cmp->destroy(state->cmp);
+ state->file->destroy(state->file);
+}
+
int main(int argc, char **argv)
{
int status, ret = 0;
@@ -19,10 +113,10 @@ int main(int argc, char **argv)
return 2;
}
- if (sqfs_reader_open(&sd.sqfs_old, sd.old_path))
+ if (open_sfqs(&sd.sqfs_old, sd.old_path))
return 2;
- if (sqfs_reader_open(&sd.sqfs_new, sd.new_path)) {
+ if (open_sfqs(&sd.sqfs_new, sd.new_path)) {
status = 2;
goto out_sqfs_old;
}
@@ -35,7 +129,7 @@ int main(int argc, char **argv)
}
}
- ret = node_compare(&sd, sd.sqfs_old.fs.root, sd.sqfs_new.fs.root);
+ ret = node_compare(&sd, sd.sqfs_old.root, sd.sqfs_new.root);
if (ret != 0)
goto out;
@@ -53,8 +147,8 @@ out:
} else {
status = 0;
}
- sqfs_reader_close(&sd.sqfs_new);
+ close_sfqs(&sd.sqfs_new);
out_sqfs_old:
- sqfs_reader_close(&sd.sqfs_old);
+ close_sfqs(&sd.sqfs_old);
return status;
}
diff --git a/difftool/sqfsdiff.h b/difftool/sqfsdiff.h
index d9a01c2..40c0fc5 100644
--- a/difftool/sqfsdiff.h
+++ b/difftool/sqfsdiff.h
@@ -23,11 +23,22 @@
#define MAX_WINDOW_SIZE (1024 * 1024 * 4)
typedef struct {
+ sqfs_compressor_config_t cfg;
+ sqfs_compressor_t *cmp;
+ sqfs_super_t super;
+ sqfs_file_t *file;
+ sqfs_id_table_t *idtbl;
+ sqfs_dir_reader_t *dr;
+ sqfs_tree_node_t *root;
+ data_reader_t *data;
+} sqfs_state_t;
+
+typedef struct {
const char *old_path;
const char *new_path;
int compare_flags;
- sqfs_reader_t sqfs_old;
- sqfs_reader_t sqfs_new;
+ sqfs_state_t sqfs_old;
+ sqfs_state_t sqfs_new;
bool compare_super;
const char *extract_dir;
} sqfsdiff_t;
@@ -41,18 +52,20 @@ enum {
COMPARE_EXTRACT_FILES = 0x20,
};
-int compare_dir_entries(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b);
+int compare_dir_entries(sqfsdiff_t *sd, sqfs_tree_node_t *old,
+ sqfs_tree_node_t *new);
-char *node_path(tree_node_t *n);
+char *node_path(const sqfs_tree_node_t *n);
-int compare_files(sqfsdiff_t *sd, file_info_t *a, file_info_t *b,
- const char *path);
+int compare_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old,
+ const sqfs_inode_generic_t *new, const char *path);
-int node_compare(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b);
+int node_compare(sqfsdiff_t *sd, sqfs_tree_node_t *a, sqfs_tree_node_t *b);
int compare_super_blocks(const sqfs_super_t *a, const sqfs_super_t *b);
-int extract_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new,
+int extract_files(sqfsdiff_t *sd, const sqfs_inode_generic_t *old,
+ const sqfs_inode_generic_t *new,
const char *path);
void process_options(sqfsdiff_t *sd, int argc, char **argv);
diff --git a/difftool/util.c b/difftool/util.c
index 2883a2f..5e9161a 100644
--- a/difftool/util.c
+++ b/difftool/util.c
@@ -6,9 +6,9 @@
*/
#include "sqfsdiff.h"
-char *node_path(tree_node_t *n)
+char *node_path(const sqfs_tree_node_t *n)
{
- char *path = fstree_get_path(n);
+ char *path = sqfs_tree_node_get_path(n);
if (path == NULL) {
perror("get path");
@@ -16,8 +16,7 @@ char *node_path(tree_node_t *n)
}
if (canonicalize_name(path)) {
- fputs("[BUG] canonicalization of fstree_get_path failed!!\n",
- stderr);
+ fprintf(stderr, "failed to canonicalization '%s'\n", path);
free(path);
return NULL;
}
diff --git a/include/data_reader.h b/include/data_reader.h
index 63bd539..77bdd82 100644
--- a/include/data_reader.h
+++ b/include/data_reader.h
@@ -32,26 +32,14 @@ int data_reader_dump(data_reader_t *data, const sqfs_inode_generic_t *inode,
int outfd, bool allow_sparse);
/*
- Use a file_info_t to locate and extract all blocks of the coresponding
- file and its fragment, if it has one. The entire data is dumped to the
- given file descriptor.
-
- If allow_sparse is true, try to truncate and seek forward on outfd if a
- zero block is found. If false, always write blocks of zeros to outfd.
-
- Returns 0 on success, prints error messages to stderr on failure.
- */
-int data_reader_dump_file(data_reader_t *data, file_info_t *fi, int outfd,
- bool allow_sparse);
-
-/*
Read a chunk of data from a file. Starting from 'offset' into the
uncompressed file, read 'size' bytes into 'buffer'.
Returns the number of bytes read, 0 if EOF, -1 on failure. Prints an
error message to stderr on failure.
*/
-ssize_t data_reader_read(data_reader_t *data, file_info_t *fi,
+ssize_t data_reader_read(data_reader_t *data,
+ const sqfs_inode_generic_t *inode,
uint64_t offset, void *buffer, size_t size);
#endif /* DATA_READER_H */
diff --git a/lib/sqfshelper/data_reader.c b/lib/sqfshelper/data_reader.c
index 0c982d7..0780da0 100644
--- a/lib/sqfshelper/data_reader.c
+++ b/lib/sqfshelper/data_reader.c
@@ -247,113 +247,64 @@ fail_sparse:
return -1;
}
-int data_reader_dump_file(data_reader_t *data, file_info_t *fi, int outfd,
- bool allow_sparse)
-{
- uint64_t filesz = fi->size;
- size_t fragsz = fi->size % data->block_size;
- size_t count = fi->size / data->block_size;
- off_t off = fi->startblock;
- size_t i, diff;
-
- if (fragsz != 0 && (fi->fragment_offset >= data->block_size ||
- fi->fragment == 0xFFFFFFFF)) {
- fragsz = 0;
- ++count;
- }
-
- if (allow_sparse && ftruncate(outfd, filesz))
- goto fail_sparse;
-
- for (i = 0; i < count; ++i) {
- diff = filesz > data->block_size ? data->block_size : filesz;
- filesz -= diff;
-
- if (SQFS_IS_SPARSE_BLOCK(fi->block_size[i])) {
- if (allow_sparse) {
- if (lseek(outfd, diff, SEEK_CUR) == (off_t)-1)
- goto fail_sparse;
- continue;
- }
- memset(data->block, 0, diff);
- } else {
- if (precache_data_block(data, off, fi->block_size[i]))
- return -1;
- off += SQFS_ON_DISK_BLOCK_SIZE(fi->block_size[i]);
- }
-
- if (write_data("writing uncompressed block",
- outfd, data->block, diff)) {
- return -1;
- }
- }
-
- if (fragsz > 0) {
- if (precache_fragment_block(data, fi->fragment))
- return -1;
-
- if (fi->fragment_offset >= data->frag_used)
- goto fail_range;
-
- if ((fi->fragment_offset + fragsz - 1) >= data->frag_used)
- goto fail_range;
-
- if (write_data("writing uncompressed fragment", outfd,
- (char *)data->frag_block + fi->fragment_offset,
- fragsz)) {
- return -1;
- }
- }
-
- return 0;
-fail_range:
- fputs("attempted to read past fragment block limits\n", stderr);
- return -1;
-fail_sparse:
- perror("creating sparse output file");
- return -1;
-}
-
-ssize_t data_reader_read(data_reader_t *data, file_info_t *fi,
+ssize_t data_reader_read(data_reader_t *data,
+ const sqfs_inode_generic_t *inode,
uint64_t offset, void *buffer, size_t size)
{
- size_t i, diff, fragsz, count, total = 0;
- off_t off;
+ uint32_t frag_idx, frag_off;
+ size_t i, diff, total = 0;
+ uint64_t off, filesz;
char *ptr;
- /* work out block count and fragment size */
- fragsz = fi->size % data->block_size;
- count = fi->size / data->block_size;
-
- if (fragsz != 0 && (fi->fragment_offset >= data->block_size ||
- fi->fragment == 0xFFFFFFFF)) {
- fragsz = 0;
- ++count;
+ /* work out file location and size */
+ if (inode->base.type == SQFS_INODE_EXT_FILE) {
+ off = inode->data.file_ext.blocks_start;
+ filesz = inode->data.file_ext.file_size;
+ frag_idx = inode->data.file_ext.fragment_idx;
+ frag_off = inode->data.file_ext.fragment_offset;
+ } else {
+ off = inode->data.file.blocks_start;
+ filesz = inode->data.file.file_size;
+ frag_idx = inode->data.file.fragment_index;
+ frag_off = inode->data.file.fragment_offset;
}
- /* work out block index and on-disk location */
- off = fi->startblock;
+ /* find location of the first block */
i = 0;
- while (offset > data->block_size && i < count) {
- off += SQFS_ON_DISK_BLOCK_SIZE(fi->block_size[i++]);
+ while (offset > data->block_size && i < inode->num_file_blocks) {
+ off += SQFS_ON_DISK_BLOCK_SIZE(inode->block_sizes[i++]);
offset -= data->block_size;
+
+ if (filesz >= data->block_size) {
+ filesz -= data->block_size;
+ } else {
+ filesz = 0;
+ }
}
/* copy data from blocks */
- while (i < count && size > 0) {
+ while (i < inode->num_file_blocks && size > 0 && filesz > 0) {
diff = data->block_size - offset;
if (size < diff)
- size = diff;
+ diff = size;
- if (SQFS_IS_SPARSE_BLOCK(fi->block_size[i])) {
+ if (SQFS_IS_SPARSE_BLOCK(inode->block_sizes[i])) {
memset(buffer, 0, diff);
} else {
- if (precache_data_block(data, off, fi->block_size[i]))
+ if (precache_data_block(data, off,
+ inode->block_sizes[i])) {
return -1;
+ }
memcpy(buffer, (char *)data->block + offset, diff);
- off += SQFS_ON_DISK_BLOCK_SIZE(fi->block_size[i]);
+ off += SQFS_ON_DISK_BLOCK_SIZE(inode->block_sizes[i]);
+ }
+
+ if (filesz >= data->block_size) {
+ filesz -= data->block_size;
+ } else {
+ filesz = 0;
}
++i;
@@ -364,32 +315,30 @@ ssize_t data_reader_read(data_reader_t *data, file_info_t *fi,
}
/* copy from fragment */
- if (i == count && size > 0 && fragsz > 0) {
- if (precache_fragment_block(data, fi->fragment))
+ if (i == inode->num_file_blocks && size > 0 && filesz > 0) {
+ if (precache_fragment_block(data, frag_idx))
return -1;
- if (fi->fragment_offset >= data->frag_used)
+ if (frag_off >= data->frag_used)
goto fail_range;
- if ((fi->fragment_offset + fragsz - 1) >= data->frag_used)
+ if (frag_off + filesz > data->frag_used)
goto fail_range;
- ptr = (char *)data->frag_block + fi->fragment_offset;
- ptr += offset;
+ if (offset >= filesz)
+ return total;
- if (offset >= fragsz) {
- offset = 0;
- size = 0;
- }
+ if (offset + size > filesz)
+ size = filesz - offset;
- if (offset + size > fragsz)
- size = fragsz - offset;
+ if (size == 0)
+ return total;
- if (size > 0) {
- memcpy(buffer, ptr + offset, size);
- total += size;
- }
+ ptr = (char *)data->frag_block + frag_off + offset;
+ memcpy(buffer, ptr, size);
+ total += size;
}
+
return total;
fail_range:
fputs("attempted to read past fragment block limits\n", stderr);