aboutsummaryrefslogtreecommitdiff
path: root/difftool
diff options
context:
space:
mode:
Diffstat (limited to 'difftool')
-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
7 files changed, 206 insertions, 65 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;
}