/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
1
/*
2
 * patch-delta.c:
3
 * recreate a buffer from a source and the delta produced by diff-delta.c
4
 *
5
 * (C) 2005 Nicolas Pitre <nico@cam.org>
6
 *
7
 * This code is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License version 2 as
9
 * published by the Free Software Foundation.
10
 */
11
12
#include "delta.h"
13
14
void *patch_delta(const void *src_buf, unsigned long src_size,
15
		  const void *delta_buf, unsigned long delta_size,
16
		  unsigned long *dst_size)
17
{
18
	const unsigned char *data, *top;
19
	unsigned char *dst_buf, *out, cmd;
20
	unsigned long size;
21
22
	if (delta_size < DELTA_SIZE_MIN)
23
		return NULL;
24
25
	data = delta_buf;
26
	top = (const unsigned char *) delta_buf + delta_size;
27
28
	/* make sure the orig file size matches what we expect */
29
	size = get_delta_hdr_size(&data, top);
0.23.10 by John Arbash Meinel
Allowing the source bytes to be longer than expected.
30
	/* MOD: We allow a bigger source, assuming we only compressed
31
	   against the first bytes. */
32
	if (size > src_size)
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
33
		return NULL;
0.23.10 by John Arbash Meinel
Allowing the source bytes to be longer than expected.
34
	src_size = size;
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
35
36
	/* now the result size */
37
	size = get_delta_hdr_size(&data, top);
0.23.5 by John Arbash Meinel
Minor changes to get diff-delta.c and patch-delta.c to compile.
38
	dst_buf = malloc(size + 1);
39
    if (dst_buf == NULL) {
40
        /* XXX: Out of memory */
41
        return NULL;
42
    }
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
43
	dst_buf[size] = 0;
44
45
	out = dst_buf;
46
	while (data < top) {
47
		cmd = *data++;
48
		if (cmd & 0x80) {
49
			unsigned long cp_off = 0, cp_size = 0;
50
			if (cmd & 0x01) cp_off = *data++;
51
			if (cmd & 0x02) cp_off |= (*data++ << 8);
52
			if (cmd & 0x04) cp_off |= (*data++ << 16);
53
			if (cmd & 0x08) cp_off |= (*data++ << 24);
54
			if (cmd & 0x10) cp_size = *data++;
55
			if (cmd & 0x20) cp_size |= (*data++ << 8);
56
			if (cmd & 0x40) cp_size |= (*data++ << 16);
57
			if (cp_size == 0) cp_size = 0x10000;
58
			if (cp_off + cp_size < cp_size ||
59
			    cp_off + cp_size > src_size ||
60
			    cp_size > size)
61
				break;
62
			memcpy(out, (char *) src_buf + cp_off, cp_size);
63
			out += cp_size;
64
			size -= cp_size;
65
		} else if (cmd) {
66
			if (cmd > size)
67
				break;
68
			memcpy(out, data, cmd);
69
			out += cmd;
70
			data += cmd;
71
			size -= cmd;
72
		} else {
73
			/*
74
			 * cmd == 0 is reserved for future encoding
75
			 * extensions. In the mean time we must fail when
76
			 * encountering them (might be data corruption).
77
			 */
0.23.5 by John Arbash Meinel
Minor changes to get diff-delta.c and patch-delta.c to compile.
78
			/* XXX: error("unexpected delta opcode 0"); */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
79
			goto bad;
80
		}
81
	}
82
83
	/* sanity check */
84
	if (data != top || size != 0) {
0.23.5 by John Arbash Meinel
Minor changes to get diff-delta.c and patch-delta.c to compile.
85
		/* XXX: error("delta replay has gone wild"); */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
86
		bad:
87
		free(dst_buf);
88
		return NULL;
89
	}
90
91
	*dst_size = out - dst_buf;
92
	return dst_buf;
93
}