diff options
Diffstat (limited to 'difftool')
| -rw-r--r-- | difftool/compare_files.c | 91 | ||||
| -rw-r--r-- | difftool/sqfsdiff.c | 74 | ||||
| -rw-r--r-- | difftool/sqfsdiff.h | 4 | 
3 files changed, 118 insertions, 51 deletions
| diff --git a/difftool/compare_files.c b/difftool/compare_files.c index 605df84..df767c1 100644 --- a/difftool/compare_files.c +++ b/difftool/compare_files.c @@ -9,14 +9,45 @@  static unsigned char old_buf[MAX_WINDOW_SIZE];  static unsigned char new_buf[MAX_WINDOW_SIZE]; +static int open_file(int dirfd, const char *prefix, const char *path) +{ +	int fd = openat(dirfd, path, O_RDONLY); + +	if (fd < 0) { +		fprintf(stderr, "open %s/%s: %s\n", +			prefix, path, strerror(errno)); +	} + +	return fd; +} + +static int read_blob(const char *prefix, const char *path, bool is_dir, +		     int fd, data_reader_t *rd, file_info_t *fi, void *buffer, +		     off_t offset, size_t size) +{ +	ssize_t ret; + +	if (is_dir) { +		ret = read_data_at(path, offset, fd, buffer, size); +	} else { +		ret = data_reader_read(rd, fi, offset, buffer, size); +		ret = (ret < 0 || (size_t)ret < size) ? -1 : 0; +	} + +	if (ret) { +		fprintf(stderr, "Failed to read %s from %s\n", +			path, prefix); +		return -1; +	} + +	return 0; +} +  int compare_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new,  		  const char *path)  { -	char new_name[strlen(sd->new_path) + strlen(path) + 2]; -	char old_name[strlen(sd->old_path) + strlen(path) + 2]; -	int old_fd = -1, new_fd = -1, status = 0; +	int old_fd = -1, new_fd = -1, status = 0, ret;  	uint64_t offset, diff; -	ssize_t ret;  	if (old->size != new->size)  		goto out_different; @@ -25,23 +56,15 @@ int compare_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new,  		return 0;  	if (sd->old_is_dir) { -		sprintf(old_name, "%s/%s", sd->old_path, path); - -		old_fd = open(old_name, O_RDONLY); -		if (old_fd < 0) { -			perror(old_name); +		old_fd = open_file(sd->old_fd, sd->old_path, path); +		if (old_fd < 0)  			goto fail; -		}  	}  	if (sd->new_is_dir) { -		sprintf(new_name, "%s/%s", sd->new_path, path); - -		new_fd = open(new_name, O_RDONLY); -		if (new_fd < 0) { -			perror(new_name); +		new_fd = open_file(sd->new_fd, sd->new_path, path); +		if (new_fd < 0)  			goto fail; -		}  	}  	for (offset = 0; offset < old->size; offset += diff) { @@ -50,33 +73,15 @@ int compare_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new,  		if (diff > MAX_WINDOW_SIZE)  			diff = MAX_WINDOW_SIZE; -		if (sd->old_is_dir) { -			if (read_data_at(old_name, offset, old_fd, -					 old_buf, diff)) -				goto out; -		} else { -			ret = data_reader_read(sd->sqfs_old.data, old, offset, -					       old_buf, diff); -			if (ret < 0 || (size_t)ret < diff) { -				fprintf(stderr, "Failed to read %s from %s\n", -					path, sd->old_path); -				return -1; -			} -		} - -		if (sd->new_is_dir) { -			if (read_data_at(new_name, offset, new_fd, -					 new_buf, diff)) -				goto out; -		} else { -			ret = data_reader_read(sd->sqfs_new.data, new, offset, -					       new_buf, diff); -			if (ret < 0 || (size_t)ret < diff) { -				fprintf(stderr, "Failed to read %s from %s\n", -					path, sd->new_path); -				return -1; -			} -		} +		ret = read_blob(sd->old_path, path, sd->old_is_dir, old_fd, +				sd->sqfs_old.data, old, old_buf, offset, diff); +		if (ret) +			goto fail; + +		ret = read_blob(sd->new_path, path, sd->new_is_dir, new_fd, +				sd->sqfs_new.data, new, new_buf, offset, diff); +		if (ret) +			goto fail;  		if (memcmp(old_buf, new_buf, diff) != 0)  			goto out_different; diff --git a/difftool/sqfsdiff.c b/difftool/sqfsdiff.c index 2bc733b..601ffba 100644 --- a/difftool/sqfsdiff.c +++ b/difftool/sqfsdiff.c @@ -19,12 +19,60 @@ int main(int argc, char **argv)  			return EXIT_FAILURE;  	} -	if (sqfs_reader_open(&sd.sqfs_old, sd.old_path, 0)) -		return 2; +	/* open first source */ +	sd.old_fd = open(sd.old_path, O_DIRECTORY | O_PATH | O_RDONLY); +	if (sd.old_fd < 0) { +		if (errno == ENOTDIR) { +			sd.old_is_dir = false; -	if (sqfs_reader_open(&sd.sqfs_new, sd.new_path, 0)) { -		status = 2; -		goto out_sqfs_old; +			if (sqfs_reader_open(&sd.sqfs_old, sd.old_path, 0)) +				return 2; +		} else { +			perror(sd.old_path); +			return 2; +		} +	} else { +		sd.old_is_dir = true; +		if (fstree_init(&sd.sqfs_old.fs, 512, NULL)) +			return 2; + +		if (fstree_from_dir(&sd.sqfs_old.fs, sd.old_path, 0)) { +			fstree_cleanup(&sd.sqfs_old.fs); +			return 2; +		} + +		tree_node_sort_recursive(sd.sqfs_old.fs.root); +	} + +	/* open second source */ +	sd.new_fd = open(sd.new_path, O_DIRECTORY | O_PATH | O_RDONLY); +	if (sd.new_fd < 0) { +		if (errno == ENOTDIR) { +			sd.new_is_dir = false; + +			if (sqfs_reader_open(&sd.sqfs_new, sd.new_path, 0)) { +				status = 2; +				goto out_sqfs_old; +			} +		} else { +			status = 2; +			perror(sd.new_path); +			goto out_sqfs_old; +		} +	} else { +		sd.new_is_dir = true; +		if (fstree_init(&sd.sqfs_new.fs, 512, NULL)) { +			status = 2; +			goto out_sqfs_old; +		} + +		if (fstree_from_dir(&sd.sqfs_new.fs, sd.new_path, 0)) { +			status = 2; +			fstree_cleanup(&sd.sqfs_old.fs); +			goto out_sqfs_old; +		} + +		tree_node_sort_recursive(sd.sqfs_new.fs.root);  	}  	if (sd.extract_dir != NULL) { @@ -39,7 +87,7 @@ int main(int argc, char **argv)  	if (ret != 0)  		goto out; -	if (sd.compare_super) { +	if (sd.compare_super && !sd.old_is_dir && !sd.new_is_dir) {  		ret = compare_super_blocks(&sd.sqfs_old.super,  					   &sd.sqfs_new.super);  		if (ret != 0) @@ -53,8 +101,18 @@ out:  	} else {  		status = 0;  	} -	sqfs_reader_close(&sd.sqfs_new); +	if (sd.new_is_dir) { +		close(sd.new_fd); +		fstree_cleanup(&sd.sqfs_new.fs); +	} else { +		sqfs_reader_close(&sd.sqfs_new); +	}  out_sqfs_old: -	sqfs_reader_close(&sd.sqfs_old); +	if (sd.old_is_dir) { +		close(sd.old_fd); +		fstree_cleanup(&sd.sqfs_old.fs); +	} else { +		sqfs_reader_close(&sd.sqfs_old); +	}  	return status;  } diff --git a/difftool/sqfsdiff.h b/difftool/sqfsdiff.h index ce6929f..836b499 100644 --- a/difftool/sqfsdiff.h +++ b/difftool/sqfsdiff.h @@ -33,6 +33,10 @@ typedef struct {  	bool new_is_dir;  	bool compare_super;  	const char *extract_dir; + +	/* holds the coresponding dirfds if old or new is a directory */ +	int old_fd; +	int new_fd;  } sqfsdiff_t;  enum { | 
