// search function modification and the error handling.
#define _CRT_SECURE_NO_WARNINGS
+#include <assert.h>
#include <sys/types.h>
#include <err.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
+#include <getopt.h>
#include <Alloc.h>
#include <7zFile.h>
#define PATCH_FILE_FORMAT_MOD // no accumulation of diff and extra in db and eb; immediate write; also write all 3 parts of control stmt at same time
#define MULTI_THREADING 1 // only with #define CONST_MEMORY_USAGE or #define MAX_MATCH_SIZE
#define TIME_LIMIT_CHECK 300
+#define TEMP_PATCH_NAME "temp_patch"
/* Take care :
1) Use either (MAX_MATCH_SIZE or CONST_MEMORY_USAGE) or (none of both).
FILE * pfbz2;
};
+enum compression_method {
+ CM_LZMA,
+};
+
+struct bsdiff_info {
+ const char *old_file;
+ const char *new_file;
+ const char *patch_file;
+ enum compression_method comp_method;
+};
+
struct data_thread data;
int Function(int);
buf[7] |= 0x80;
}
-int create_patch(int argc, const char *argv[], int offset_oldscore)
+int create_patch(const char *old_file, const char *new_file, const char *temp_patch, int offset_oldscore)
{
+ assert(old_file);
+ assert(new_file);
+
data.num_threads = MULTI_THREADING;
data.new = (u_char **)malloc(sizeof(u_char *)*data.num_threads);
- if (argc != 4)
- errx(1, "usage: %s oldfile newfile patchfile\n", argv[0]);
/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
that we never try to malloc(0) and get a NULL pointer */
- if (((data.fd = open(argv[1], O_RDONLY, 0)) < 0) ||
+ if (((data.fd = open(old_file, O_RDONLY, 0)) < 0) ||
((data.oldsize = lseek(data.fd, 0, SEEK_END)) == -1) ||
((data.old = malloc(data.oldsize + 1)) == NULL) ||
(lseek(data.fd, 0, SEEK_SET) != 0) ||
(read(data.fd, data.old, data.oldsize) != data.oldsize) ||
(close(data.fd) == -1))
- err(1, "%s", argv[1]);
+ err(1, "%s", old_file);
data.I = malloc((data.oldsize + 1) * sizeof(saidx_t));
divsufsort(data.old, data.I, data.oldsize);
/* Allocate newsize+1 bytes instead of newsize bytes to ensure
that we never try to malloc(0) and get a NULL pointer */
- if (((data.fd = open(argv[2], O_RDONLY, 0)) < 0) ||
+ if (((data.fd = open(new_file, O_RDONLY, 0)) < 0) ||
((data.newsize = lseek(data.fd, 0, SEEK_END)) == -1) ||
(lseek(data.fd, 0, SEEK_SET) != 0))
- err(1, "%s", argv[2]);
+ err(1, "%s", new_file);
data.size_thread = (data.newsize / data.num_threads);
unsigned int j;
if (((data.new[j] = (u_char *)malloc(sizeof(u_char) * (data.size_thread + 1))) == NULL) ||
(lseek(data.fd, 0, SEEK_CUR) != j * data.size_thread) ||
(read(data.fd, data.new[j], data.size_thread) != data.size_thread))
- err(1, "%s", argv[2]);
+ err(1, "%s", new_file);
} else {
if (((data.new[j] = (u_char *)malloc(sizeof(u_char) * (data.newsize - (j * data.size_thread) + 1))) == NULL) ||
(lseek(data.fd, 0, SEEK_CUR) != j * data.size_thread) ||
(read(data.fd, data.new[j], data.newsize - (j * data.size_thread)) != data.newsize - (j * data.size_thread)))
- err(1, "here %s", argv[2]);
+ err(1, "here %s", new_file);
}
}
if ((close(data.fd) == -1))
- err(1, "%s", argv[2]);
+ err(1, "%s", new_file);
/* Create the patch file */
- if ((data.pf = fopen("temp_patch", "w")) == NULL)
- err(1, "%s", "temp_patch");
+ if ((data.pf = fopen(temp_patch, "w")) == NULL)
+ err(1, "%s", temp_patch);
/* Header is
0 8 "BSDIFF40"
offtout(data.newsize, data.header + 8);
if (fwrite(data.header, 16, 1, data.pf) != 1)
- err(1, "fwrite(%s)", "temp_patch");
+ err(1, "fwrite(%s)", temp_patch);
/* Compute the differences, writing ctrl as we go */
data.pfbz2 = data.pf;
#ifdef TIME_LIMIT_CHECK
if (ret != 0) {
printf("bsdiff fails to create delta with offset score %d\n", offset_oldscore);
- printf("Old: [%s] -> New: [%s]\n", argv[1], argv[2]);
+ printf("Old: [%s] -> New: [%s]\n", old_file, new_file);
}
#endif
/* Seek to the beginning, write the header, and close the file */
err(1, "fseeko");
if (fwrite(data.header, 16, 1, data.pf) != 1)
- err(1, "fwrite(%s)", "temp_patch");
+ err(1, "fwrite(%s)", temp_patch);
if (fclose(data.pf))
err(1, "fclose");
/* Free the memory we used */
#define OUT_BUF_SIZE (1 << 16)
-static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
+static SRes lzma_encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
{
CLzmaEncHandle enc;
SRes res;
return res;
}
-int main2(int numArgs, const char *args[], char *rs, int rs_size)
+int lzma_compress(const char *input_file, const char *output_file, char *rs, int rs_size)
{
+ assert(patch_file);
+ assert(rs);
+
CFileSeqInStream inStream;
CFileOutStream outStream;
int res;
if (t4 != 4 || t8 != 8)
return PrintError(rs, "Incorrect UInt32 or UInt64", rs_size);
- if (InFile_Open(&inStream.file, "temp_patch") != 0)
+ if (InFile_Open(&inStream.file, input_file) != 0)
return PrintError(rs, "Can not open input file", rs_size);
- if (OutFile_Open(&outStream.file, args[3]) != 0)
+ if (OutFile_Open(&outStream.file, output_file) != 0)
return PrintError(rs, "Can not open output file", rs_size);
UInt64 fileSize;
File_GetLength(&inStream.file, &fileSize);
- res = Encode(&outStream.s, &inStream.s, fileSize, rs);
+ res = lzma_encode(&outStream.s, &inStream.s, fileSize, rs);
File_Close(&outStream.file);
File_Close(&inStream.file);
return 0;
}
-int MY_CDECL main(int numArgs, const char *args[])
+void print_help(const char *arg0)
+{
+ assert(arg0);
+ errx(1, "ss_bsdiff Version 5.0\nUsage: %s oldfile newfile patchfile\n", arg0);
+}
+
+int parse_args(struct bsdiff_info *info, int argc, char *argv[])
+{
+ assert(info);
+ assert(argv);
+
+ struct option long_options[] = {
+ {"compression", optional_argument, NULL, 'c'},
+ {0, 0 , 0, 0}
+ };
+
+ int opt;
+
+ while ((opt = getopt_long(argc, argv, "c:", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'c':
+ if (strcmp("lzma", optarg) == 0)
+ info->comp_method = CM_LZMA;
+ else {
+ err(1, "Unknown compression method: %s", optarg);
+ return -1;
+ }
+ }
+ }
+
+ if (optind + 2 >= argc) {
+ err(1, "Not enough parameters");
+ print_help(argv[0]);
+ return -1;
+ }
+
+ info->old_file = argv[optind];
+ info->new_file = argv[optind+1];
+ info->patch_file = argv[optind+2];
+
+ return 0;
+}
+
+int MY_CDECL main(int argc, char *argv[])
{
char rs[800] = { 0 };
- if (numArgs != 4)
- errx(1, "ss_bsdiff Version 5.0\nUsage: ss_bsdiff oldfile newfile patchfile\n");
- int ret = create_patch(numArgs, args, 8);
+ struct bsdiff_info info;
+ if (parse_args(&info, argc, argv) != 0)
+ return 1;
+
+ int ret = create_patch(info.old_file, info.new_file, TEMP_PATCH_NAME, 8);
#ifdef TIME_LIMIT_CHECK
if (ret != 0) {
printf("Trying with offset score 2\n");
- ret = create_patch(numArgs, args, 2);
+ ret = create_patch(info.old_file, info.new_file, TEMP_PATCH_NAME, 2);
}
if (ret != 0) {
printf("Trying with offset score 0\n");
- ret = create_patch(numArgs, args, 0);
+ ret = create_patch(info.old_file, info.new_file, TEMP_PATCH_NAME, 0);
}
if (ret != 0)
err(1, "bsdiff fails to create delta within timelimit");
#endif
- int res = main2(numArgs, args, rs, sizeof(rs));
- if (remove("temp_patch") < 0)
- printf("Failed to remove temp_patch\n");
+ int res = lzma_compress(TEMP_PATCH_NAME, info.patch_file, rs, sizeof(rs));
+ if (remove(TEMP_PATCH_NAME) < 0)
+ printf("Failed to remove %s\n", TEMP_PATCH_NAME);
fputs(rs, stdout);
return res;
}