static void *do_fuzz(void *data) { int i = 1000; int thread = (unsigned long)data; char filename[PATH_MAXLEN]; int ret; printf("Thread %i: Fuzzing %s vs %s\n", thread, from_files[thread], to_files[thread]); sprintf(filename, OUTDIR "tempfile.%i", thread); make_bsdiff_delta(from_files[thread], to_files[thread], filename, (rand() % 10 > 8)); apply_bsdiff_delta(from_files[thread], OUTDIR "testout", filename); /* do a large number of runs and then exit, so that we can randomly pick files from an outer script */ while (i-- > 0) { char *command; /* step 3: randomly corrupt the "tempfile" into a "corrupt" file*/ corrupt_file(thread); /* step 4: run valgrind on the bspatch program with the "corrupt" file */ if (asprintf(&command, "valgrind --leak-check=no --log-file=" OUTDIR "valgrind.log.%i bspatch %s " OUTDIR "output.%i " OUTDIR "corrupt.%i > /dev/null", thread, from_files[thread], thread, thread) <= 0) { assert(0); } ret = system(command); free(command); /* step 5: check valgrind output for failures, if failed, copy corrupt to "failed" dir */ if (check_valgrind(thread)) { int t; char *command2; t = time(NULL); if (asprintf(&command2, "mv " OUTDIR "corrupt.%i " OUTDIR "failed/corrupt.%i-%i", thread, thread, t) <= 0) { assert(0); } ret = system(command2); assert(ret == 0); free(command2); if (asprintf(&command2, "mv " OUTDIR "valgrind.log.%i " OUTDIR "failed/valgrind.%i-%i", thread, thread, t) <= 0) { assert(0); } ret = system(command2); assert(ret == 0); free(command2); if (asprintf(&command2, "cp %s " OUTDIR "failed/original.%i-%i", from_files[thread], thread, t) <= 0) { assert(0); } ret = system(command2); assert(ret == 0); free(command2); printf("x"); sleep(1); /* make sure no duplicates exist */ } else if (i % 10 == 0) { printf("."); } fflush(stdout); } return NULL; }
void __create_delta(struct file *file, int from_version) { char *original, *newfile, *outfile, *dotfile, *testnewfile, *sanitycheck; char *conf; int ret; if (file->is_link) { return; } if (file->is_deleted) { return; /* file got deleted -> by definition we cannot make a delta */ } if (file->is_dir) { return; /* cannot do this for directories yet */ } conf = config_image_base(); string_or_die(&newfile, "%s/%i/full/%s", conf, file->last_change, file->filename); string_or_die(&original, "%s/%i/full/%s", conf, from_version, file->peer->filename); free(conf); conf = config_output_dir(); string_or_die(&outfile, "%s/%i/delta/%i-%i-%s", conf, file->last_change, from_version, file->last_change, file->hash); string_or_die(&dotfile, "%s/%i/delta/.%i-%i-%s", conf, file->last_change, from_version, file->last_change, file->hash); string_or_die(&testnewfile, "%s/%i/delta/.%i-%i-%s.testnewfile", conf, file->last_change, from_version, file->last_change, file->hash); string_or_die(&sanitycheck, "cmp -s \"%s\" \"%s\"", newfile, testnewfile); LOG(file, "Making delta", "%s->%s", original, newfile); ret = xattrs_compare(original, newfile); if (ret != 0) { LOG(NULL, "xattrs have changed, don't create diff ", "%s", newfile); goto out; } ret = make_bsdiff_delta(original, newfile, dotfile, 0); if (ret < 0) { LOG(file, "Delta creation failed", "%s->%s ret is %i", original, newfile, ret); goto out; } if (ret == 1) { LOG(file, "...delta larger than newfile: FULLDL", "%s", newfile); unlink(dotfile); goto out; } /* does delta properly recreate expected content? */ ret = apply_bsdiff_delta(original, testnewfile, dotfile); if (ret != 0) { printf("Delta application failed.\n"); printf("Attempted %s->%s via diff %s\n", original, testnewfile, dotfile); LOG(file, "Delta application failed.", "Attempted %s->%s via diff %s", original, testnewfile, dotfile); #warning the above is racy..tolerate it temporarily // ok fine //unlink(testnewfile); //unlink(dotfile); ret = 0; goto out; } xattrs_copy(original, newfile); /* does xattrs have been correctly copied?*/ if (xattrs_compare(original, testnewfile) != 0) { printf("Delta application resulted in xattrs mismatch.\n"); printf("%s->%s via diff %s yielded %s\n", original, newfile, dotfile, testnewfile); LOG(file, "Delta xattrs mismatch:", "%s->%s via diff %s yielded %s", original, newfile, dotfile, testnewfile); assert(0); goto out; } ret = system(sanitycheck); if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) == 2) { printf("Sanity check system command failed %i. \n", ret); printf("%s->%s via diff %s yielded %s\n", original, newfile, dotfile, testnewfile); assert(0); goto out; } else if (WEXITSTATUS(ret) == 1) { printf("Delta application resulted in file mismatch %i. \n", ret); printf("%s->%s via diff %s yielded %s\n", original, newfile, dotfile, testnewfile); LOG(file, "Delta mismatch:", "%s->%s via diff %s yielded %s", original, newfile, dotfile, testnewfile); #warning this too will have failures due to races //unlink(testnewfile); //unlink(dotfile); ret = 0; goto out; } unlink(testnewfile); if (rename(dotfile, outfile) != 0) { if (errno == ENOENT) { LOG(NULL, "dotfile:", " %s does not exist", dotfile); } LOG(NULL, "Failed to rename", ""); } out: free(sanitycheck); free(testnewfile); free(conf); free(newfile); free(original); free(outfile); free(dotfile); }
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; }