/* * Software Updater - server side * * Copyright © 2012-2016 Intel Corporation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2 or later of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: * Arjan van de Ven * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "swupd.h" #include "xattrs.h" void __create_delta(struct file *file, int from_version, char *from_hash) { char *original, *newfile, *outfile, *dotfile, *testnewfile, *conf; int ret; if (!file->is_file || !file->peer->is_file) { return; /* only support deltas between two regular files right now */ } 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-%s", conf, file->last_change, from_version, file->last_change, from_hash, file->hash); string_or_die(&dotfile, "%s/%i/delta/.%i-%i-%s-%s", conf, file->last_change, from_version, file->last_change, from_hash, file->hash); string_or_die(&testnewfile, "%s/%i/delta/.%i-%i-%s-%s.testnewfile", conf, file->last_change, from_version, file->last_change, from_hash, file->hash); 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, testnewfile); /* 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; } char *const sanitycheck[] = { "cmp", "-s", newfile, testnewfile, NULL }; ret = system_argv(sanitycheck); if (ret == -1 || 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 (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(testnewfile); free(conf); free(newfile); free(original); free(outfile); free(dotfile); } void prepare_delta_dir(struct manifest *manifest) { char *path; char *conf; printf("Preparing delta directory \n"); conf = config_output_dir(); string_or_die(&path, "%s/%i", conf, manifest->version); if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { if (errno != EEXIST) { LOG(NULL, "Failed to create directory ", "%s", path); return; } } free(path); string_or_die(&path, "%s/%i/delta/", conf, manifest->version); if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { if (errno != EEXIST) { LOG(NULL, "Failed to create directory ", "%s", path); return; } } free(path); free(conf); }