bool verify_file(struct file *file, char *filename) { struct file *local = calloc(1, sizeof(struct file)); if (local == NULL) { abort(); } local->filename = file->filename; local->use_xattrs = true; populate_file_struct(local, filename); if (compute_hash(local, filename) != 0) { free(local); return false; } /* Check if manifest hash matches local file hash */ if (hash_equal(file->hash, local->hash)) { free(local); return true; } else { free(local); return false; } }
static mrb_value mrb_hash_eql(mrb_state *mrb, mrb_value hash1) { mrb_value hash2; mrb_get_args(mrb, "o", &hash2); return hash_equal(mrb, hash1, hash2, TRUE); }
static bool hash_needs_work(struct file *file, char *hash) { if (cmdline_option_quick) { return (hash_is_zeros(hash)); } else { return (!hash_equal(file->hash, hash)); } }
/* try to insert the file into the hashmap download queue * returns 1 if no download is needed * returns 0 if download is needed * returns -1 if error */ static int swupd_curl_hashmap_insert(struct file *file) { struct list *iter; struct file *tmp; char *tar_dotfile; char *targetfile; struct stat stat; int hashmap_index = file->hash[0]; struct swupd_curl_hashbucket *bucket = &swupd_curl_hashmap[hashmap_index]; pthread_mutex_lock(&bucket->mutex); iter = bucket->list; while (iter) { tmp = iter->data; if (hash_equal(tmp->hash, file->hash)) { // hash already in download queue pthread_mutex_unlock(&bucket->mutex); return 1; } iter = iter->next; } // if valid target file is already here, no need to download string_or_die(&targetfile, "%s/staged/%s", state_dir, file->hash); if (lstat(targetfile, &stat) == 0) { if (verify_file(file, targetfile)) { free(targetfile); pthread_mutex_unlock(&bucket->mutex); return 1; } } free(targetfile); // hash not in queue and not present in staged // clean up in case any prior download failed in a partial state string_or_die(&tar_dotfile, "%s/download/.%s.tar", state_dir, file->hash); unlink(tar_dotfile); free(tar_dotfile); // queue the hash for download iter = bucket->list; if ((iter = list_prepend_data(iter, file)) == NULL) { pthread_mutex_unlock(&bucket->mutex); return -1; } bucket->list = iter; pthread_mutex_unlock(&bucket->mutex); return 0; }
static int file_has_different_hash_in_manifest(struct manifest *manifest, struct file *searched_file) { struct list *list; struct file *file; list = list_head(manifest->files); while (list) { file = list->data; list = list->next; if (file->is_deleted) { continue; } if (!strcmp(file->filename, searched_file->filename) && !hash_equal(file->hash, searched_file->hash)) { return 1; } } return 0; }
static bool hash_is_ones(char *hash) { return hash_equal("1111111111111111111111111111111111111111111111111111111111111111", hash); }
bool hash_is_zeros(char *hash) { return hash_equal("0000000000000000000000000000000000000000000000000000000000000000", hash); }
static gboolean file_equal(gconstpointer a, gconstpointer b){ struct file_item* fa = a; struct file_item* fb = b; return hash_equal(fa->hash, fb->hash); }
static VALUE rhash_eql(VALUE hash1, SEL sel, VALUE hash2) { return hash_equal(hash1, hash2, true); }
VALUE rb_hash_equal(VALUE hash1, VALUE hash2) { return hash_equal(hash1, hash2, false); }
int main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) { int ret; int algo; struct timeval before, after; struct stat st1, st2; struct file *file1, *file2; ret = stat(argv[1], &st1); if (ret) { exit(0); } ret = stat(argv[2], &st2); if (ret) { exit(0); } file1 = calloc(1, sizeof(struct file)); assert(file1); file1->use_xattrs = true; file1->filename = strdup(argv[2]); file2 = calloc(1, sizeof(struct file)); assert(file2); file2->use_xattrs = true; file1->filename = strdup("result"); populate_file_struct(file1, argv[2]); ret = compute_hash(file1, argv[2]); if ((ret != 0) || hash_is_zeros(file1->hash)) { printf("Hash computation failed\n"); exit(0); } for (algo = 0; algo < BSDIFF_ENC_LAST; algo++) { struct stat bu; int i; time_t start; unlink("output.bsdiff"); make_bsdiff_delta(argv[1], argv[2], "output.bsdiff", algo); stat("output.bsdiff", &bu); start = time(NULL); gettimeofday(&before, NULL); for (i = 0; i < 10000; i++) { ret = apply_bsdiff_delta(argv[1], "result", "output.bsdiff"); if (i > 500 && time(NULL) - start > 5) { break; } } gettimeofday(&after, NULL); populate_file_struct(file1, "result"); ret = compute_hash(file2, "result"); if ((ret != 0) || hash_is_zeros(file2->hash)) { printf("Hash computation failed\n"); exit(0); } if (!hash_equal(file1->hash, file2->hash)) { printf("Hash mismatch for algorithm %i \n", algo); exit(0); } unlink("result"); b[algo] = before.tv_sec + before.tv_usec / 1000000.0; a[algo] = after.tv_sec + after.tv_usec / 1000000.0; count[algo] = i / 5000.0; size[algo] = bu.st_size; } printf("file, %s, orgsize, %i, best, %i, unc, %i, %5.3f, bzip, %i, %5.3f, gzip, %i, %5.3f, xz, %i, %5.3f, zeros, %i, %5.3f\n", argv[1], (int)(st1.st_size + st2.st_size) / 2, size[0], size[1], (a[1] - b[1]) / count[1], size[2], (a[2] - b[2]) / count[2], size[3], (a[3] - b[3]) / count[3], size[4], (a[4] - b[4]) / count[4], size[5], (a[5] - b[5]) / count[5]); return ret; }