#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <sys/types.h>
#include "zlib.h"
#include "imgdiff.h"
size_t source_start;
size_t source_len;
+ off_t* I; // used by bsdiff
+
// --- for CHUNK_DEFLATE chunks only: ---
// original (compressed) deflate data
}
}
+// from bsdiff.c
+int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* new, off_t newsize,
+ const char* patch_filename);
+
unsigned char* ReadZip(const char* filename,
int* num_chunks, ImageChunk** chunks,
int include_pseudo_chunk) {
curr->len = st.st_size;
curr->data = img;
curr->filename = NULL;
+ curr->I = NULL;
++curr;
++*num_chunks;
}
curr->deflate_len = temp_entries[nextentry].deflate_len;
curr->deflate_data = img + pos;
curr->filename = temp_entries[nextentry].filename;
+ curr->I = NULL;
curr->len = temp_entries[nextentry].uncomp_len;
curr->data = malloc(curr->len);
}
curr->data = img + pos;
curr->filename = NULL;
+ curr->I = NULL;
pos += curr->len;
++*num_chunks;
curr->type = CHUNK_NORMAL;
curr->len = GZIP_HEADER_LEN;
curr->data = p;
+ curr->I = NULL;
pos += curr->len;
p += curr->len;
curr->type = CHUNK_DEFLATE;
curr->filename = NULL;
+ curr->I = NULL;
// We must decompress this chunk in order to discover where it
// ends, and so we can put the uncompressed data and its length
curr->start = pos;
curr->len = GZIP_FOOTER_LEN;
curr->data = img+pos;
+ curr->I = NULL;
pos += curr->len;
p += curr->len;
*chunks = realloc(*chunks, *num_chunks * sizeof(ImageChunk));
ImageChunk* curr = *chunks + (*num_chunks-1);
curr->start = pos;
+ curr->I = NULL;
// 'pos' is not the offset of the start of a gzip chunk, so scan
// forward until we find a gzip header.
}
}
- char stemp[] = "/tmp/imgdiff-src-XXXXXX";
- char ttemp[] = "/tmp/imgdiff-tgt-XXXXXX";
char ptemp[] = "/tmp/imgdiff-patch-XXXXXX";
- mkstemp(stemp);
- mkstemp(ttemp);
mkstemp(ptemp);
- FILE* f = fopen(stemp, "wb");
- if (f == NULL) {
- fprintf(stderr, "failed to open src chunk %s: %s\n",
- stemp, strerror(errno));
- return NULL;
- }
- if (fwrite(src->data, 1, src->len, f) != src->len) {
- fprintf(stderr, "failed to write src chunk to %s: %s\n",
- stemp, strerror(errno));
- return NULL;
- }
- fclose(f);
-
- f = fopen(ttemp, "wb");
- if (f == NULL) {
- fprintf(stderr, "failed to open tgt chunk %s: %s\n",
- ttemp, strerror(errno));
- return NULL;
- }
- if (fwrite(tgt->data, 1, tgt->len, f) != tgt->len) {
- fprintf(stderr, "failed to write tgt chunk to %s: %s\n",
- ttemp, strerror(errno));
- return NULL;
- }
- fclose(f);
-
- char cmd[200];
- sprintf(cmd, "bsdiff %s %s %s", stemp, ttemp, ptemp);
- if (system(cmd) != 0) {
- fprintf(stderr, "failed to run bsdiff: %s\n", strerror(errno));
+ int r = bsdiff(src->data, src->len, &(src->I), tgt->data, tgt->len, ptemp);
+ if (r != 0) {
+ fprintf(stderr, "bsdiff() failed: %d\n", r);
return NULL;
}
unsigned char* data = malloc(st.st_size);
if (tgt->type == CHUNK_NORMAL && tgt->len <= st.st_size) {
- unlink(stemp);
- unlink(ttemp);
unlink(ptemp);
tgt->type = CHUNK_RAW;
*size = st.st_size;
- f = fopen(ptemp, "rb");
+ FILE* f = fopen(ptemp, "rb");
if (f == NULL) {
fprintf(stderr, "failed to open patch %s: %s\n", ptemp, strerror(errno));
return NULL;
}
fclose(f);
- unlink(stemp);
- unlink(ttemp);
unlink(ptemp);
tgt->source_start = src->start;
return NULL;
}
+void DumpChunks(ImageChunk* chunks, int num_chunks) {
+ int i;
+ for (i = 0; i < num_chunks; ++i) {
+ printf("chunk %d: type %d start %d len %d\n",
+ i, chunks[i].type, chunks[i].start, chunks[i].len);
+ }
+}
+
int main(int argc, char** argv) {
if (argc != 4 && argc != 5) {
usage:
// Verify that the source and target images have the same chunk
// structure (ie, the same sequence of deflate and normal chunks).
+ if (!zip_mode) {
+ // Merge the gzip header and footer in with any adjacent
+ // normal chunks.
+ MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
+ MergeAdjacentNormalChunks(src_chunks, &num_src_chunks);
+ }
+
if (num_src_chunks != num_tgt_chunks) {
fprintf(stderr, "source and target don't have same number of chunks!\n");
+ printf("source chunks:\n");
+ DumpChunks(src_chunks, num_src_chunks);
+ printf("target chunks:\n");
+ DumpChunks(tgt_chunks, num_tgt_chunks);
return 1;
}
for (i = 0; i < num_src_chunks; ++i) {
if (src_chunks[i].type != tgt_chunks[i].type) {
fprintf(stderr, "source and target don't have same chunk "
"structure! (chunk %d)\n", i);
+ printf("source chunks:\n");
+ DumpChunks(src_chunks, num_src_chunks);
+ printf("target chunks:\n");
+ DumpChunks(tgt_chunks, num_tgt_chunks);
return 1;
}
}