Mercurial > hg-stable
annotate mercurial/mpatch.c @ 2543:860e9c83fc59
Include inttypes.h instead of stdint.h (fixes issue299)
Many projects use inttypes.h, too. stdint.h isn't available everywhere, e.g.
on some versions of Solaris, while inttypes.h is available everywhere where
stdint.h is.
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 30 Jun 2006 21:41:46 +0200 |
parents | 1ac0574f1768 |
children | 345bac2bc4ec |
rev | line source |
---|---|
72 | 1 /* |
2 mpatch.c - efficient binary patching for Mercurial | |
3 | |
4 This implements a patch algorithm that's O(m + nlog n) where m is the | |
5 size of the output and n is the number of patches. | |
6 | |
7 Given a list of binary patches, it unpacks each into a hunk list, | |
8 then combines the hunk lists with a treewise recursion to form a | |
9 single hunk list. This hunk list is then applied to the original | |
10 text. | |
11 | |
12 The text (or binary) fragments are copied directly from their source | |
13 Python objects into a preallocated output string to avoid the | |
14 allocation of intermediate Python objects. Working memory is about 2x | |
15 the total number of hunks. | |
16 | |
17 Copyright 2005 Matt Mackall <mpm@selenic.com> | |
18 | |
19 This software may be used and distributed according to the terms | |
20 of the GNU General Public License, incorporated herein by reference. | |
21 */ | |
22 | |
23 #include <Python.h> | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
2468
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
26 |
410
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
27 #ifdef _WIN32 |
2468
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
28 # ifdef _MSC_VER |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
29 /* msvc 6.0 has problems */ |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
30 # define inline __inline |
551 | 31 typedef unsigned long uint32_t; |
2468
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
32 # else |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
33 # include <stdint.h> |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
34 # endif |
411
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
35 static uint32_t ntohl(uint32_t x) |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
36 { |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
37 return ((x & 0x000000ffUL) << 24) | |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
38 ((x & 0x0000ff00UL) << 8) | |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
39 ((x & 0x00ff0000UL) >> 8) | |
9e9f7ab43ce2
Add 'other OS' bits to bdiff.c / style cleanups
mpm@selenic.com
parents:
410
diff
changeset
|
40 ((x & 0xff000000UL) >> 24); |
410
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
41 } |
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
42 #else |
2468
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
43 /* not windows */ |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
44 # include <sys/types.h> |
1ac0574f1768
mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2083
diff
changeset
|
45 # include <arpa/inet.h> |
2543
860e9c83fc59
Include inttypes.h instead of stdint.h (fixes issue299)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
2468
diff
changeset
|
46 # include <inttypes.h> |
410
7c678976df3e
Make mpatch.c compilable under the other `OS'
mpm@selenic.com
parents:
384
diff
changeset
|
47 #endif |
72 | 48 |
49 static char mpatch_doc[] = "Efficient binary patching."; | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
50 static PyObject *mpatch_Error; |
72 | 51 |
52 struct frag { | |
53 int start, end, len; | |
54 char *data; | |
55 }; | |
56 | |
57 struct flist { | |
58 struct frag *base, *head, *tail; | |
59 }; | |
60 | |
61 static struct flist *lalloc(int size) | |
62 { | |
128 | 63 struct flist *a = NULL; |
72 | 64 |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
65 a = (struct flist *)malloc(sizeof(struct flist)); |
128 | 66 if (a) { |
1978
10606ee61107
do proper typecasting on malloc() and calloc() calls
TK Soh <teekaysoh@yahoo.com>
parents:
1746
diff
changeset
|
67 a->base = (struct frag *)malloc(sizeof(struct frag) * size); |
2048
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
68 if (a->base) { |
128 | 69 a->head = a->tail = a->base; |
2048
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
70 return a; |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
71 } |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
72 free(a); |
8f9660c568b8
Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1978
diff
changeset
|
73 a = NULL; |
128 | 74 } |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
75 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
76 PyErr_NoMemory(); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
77 return NULL; |
72 | 78 } |
79 | |
80 static void lfree(struct flist *a) | |
81 { | |
128 | 82 if (a) { |
83 free(a->base); | |
84 free(a); | |
85 } | |
72 | 86 } |
87 | |
88 static int lsize(struct flist *a) | |
89 { | |
90 return a->tail - a->head; | |
91 } | |
92 | |
93 /* move hunks in source that are less cut to dest, compensating | |
94 for changes in offset. the last hunk may be split if necessary. | |
95 */ | |
96 static int gather(struct flist *dest, struct flist *src, int cut, int offset) | |
97 { | |
98 struct frag *d = dest->tail, *s = src->head; | |
99 int postend, c, l; | |
100 | |
101 while (s != src->tail) { | |
102 if (s->start + offset >= cut) | |
82 | 103 break; /* we've gone far enough */ |
72 | 104 |
105 postend = offset + s->start + s->len; | |
106 if (postend <= cut) { | |
107 /* save this hunk */ | |
108 offset += s->start + s->len - s->end; | |
109 *d++ = *s++; | |
110 } | |
111 else { | |
112 /* break up this hunk */ | |
113 c = cut - offset; | |
114 if (s->end < c) | |
115 c = s->end; | |
116 l = cut - offset - s->start; | |
117 if (s->len < l) | |
118 l = s->len; | |
119 | |
120 offset += s->start + l - c; | |
121 | |
122 d->start = s->start; | |
123 d->end = c; | |
124 d->len = l; | |
125 d->data = s->data; | |
126 d++; | |
127 s->start = c; | |
128 s->len = s->len - l; | |
129 s->data = s->data + l; | |
130 | |
82 | 131 break; |
72 | 132 } |
133 } | |
134 | |
135 dest->tail = d; | |
136 src->head = s; | |
137 return offset; | |
138 } | |
139 | |
140 /* like gather, but with no output list */ | |
141 static int discard(struct flist *src, int cut, int offset) | |
142 { | |
143 struct frag *s = src->head; | |
144 int postend, c, l; | |
145 | |
146 while (s != src->tail) { | |
147 if (s->start + offset >= cut) | |
82 | 148 break; |
72 | 149 |
150 postend = offset + s->start + s->len; | |
151 if (postend <= cut) { | |
152 offset += s->start + s->len - s->end; | |
153 s++; | |
154 } | |
155 else { | |
156 c = cut - offset; | |
157 if (s->end < c) | |
158 c = s->end; | |
159 l = cut - offset - s->start; | |
160 if (s->len < l) | |
161 l = s->len; | |
162 | |
163 offset += s->start + l - c; | |
164 s->start = c; | |
165 s->len = s->len - l; | |
166 s->data = s->data + l; | |
167 | |
82 | 168 break; |
72 | 169 } |
170 } | |
171 | |
172 src->head = s; | |
173 return offset; | |
174 } | |
175 | |
176 /* combine hunk lists a and b, while adjusting b for offset changes in a/ | |
177 this deletes a and b and returns the resultant list. */ | |
178 static struct flist *combine(struct flist *a, struct flist *b) | |
179 { | |
128 | 180 struct flist *c = NULL; |
181 struct frag *bh, *ct; | |
72 | 182 int offset = 0, post; |
183 | |
128 | 184 if (a && b) |
185 c = lalloc((lsize(a) + lsize(b)) * 2); | |
186 | |
187 if (c) { | |
72 | 188 |
128 | 189 for (bh = b->head; bh != b->tail; bh++) { |
190 /* save old hunks */ | |
191 offset = gather(c, a, bh->start, offset); | |
72 | 192 |
128 | 193 /* discard replaced hunks */ |
194 post = discard(a, bh->end, offset); | |
72 | 195 |
128 | 196 /* insert new hunk */ |
197 ct = c->tail; | |
198 ct->start = bh->start - offset; | |
199 ct->end = bh->end - post; | |
200 ct->len = bh->len; | |
201 ct->data = bh->data; | |
202 c->tail++; | |
203 offset = post; | |
204 } | |
205 | |
206 /* hold on to tail from a */ | |
207 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); | |
208 c->tail += lsize(a); | |
72 | 209 } |
210 | |
211 lfree(a); | |
212 lfree(b); | |
213 return c; | |
214 } | |
215 | |
216 /* decode a binary patch into a hunk list */ | |
217 static struct flist *decode(char *bin, int len) | |
218 { | |
219 struct flist *l; | |
220 struct frag *lt; | |
221 char *end = bin + len; | |
384
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
222 char decode[12]; /* for dealing with alignment issues */ |
72 | 223 |
224 /* assume worst case size, we won't have many of these lists */ | |
225 l = lalloc(len / 12); | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
226 if (!l) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
227 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
228 |
72 | 229 lt = l->tail; |
230 | |
231 while (bin < end) { | |
384
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
232 memcpy(decode, bin, 12); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
233 lt->start = ntohl(*(uint32_t *)decode); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
234 lt->end = ntohl(*(uint32_t *)(decode + 4)); |
a29decbf7475
mpatch: attempt to handle unpack alignment issues on Solaris
mpm@selenic.com
parents:
282
diff
changeset
|
235 lt->len = ntohl(*(uint32_t *)(decode + 8)); |
72 | 236 lt->data = bin + 12; |
237 bin += 12 + lt->len; | |
238 lt++; | |
239 } | |
240 | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
241 if (bin != end) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
242 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
243 PyErr_SetString(mpatch_Error, "patch cannot be decoded"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
244 lfree(l); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
245 return NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
246 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
247 |
72 | 248 l->tail = lt; |
249 return l; | |
250 } | |
251 | |
252 /* calculate the size of resultant text */ | |
253 static int calcsize(int len, struct flist *l) | |
254 { | |
255 int outlen = 0, last = 0; | |
256 struct frag *f = l->head; | |
257 | |
258 while (f != l->tail) { | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
259 if (f->start < last || f->end > len) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
260 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
261 PyErr_SetString(mpatch_Error, |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
262 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
263 return -1; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
264 } |
72 | 265 outlen += f->start - last; |
266 last = f->end; | |
267 outlen += f->len; | |
268 f++; | |
269 } | |
270 | |
271 outlen += len - last; | |
272 return outlen; | |
273 } | |
274 | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
275 static int apply(char *buf, char *orig, int len, struct flist *l) |
72 | 276 { |
277 struct frag *f = l->head; | |
278 int last = 0; | |
279 char *p = buf; | |
280 | |
281 while (f != l->tail) { | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
282 if (f->start < last || f->end > len) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
283 if (!PyErr_Occurred()) |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
284 PyErr_SetString(mpatch_Error, |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
285 "invalid patch"); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
286 return 0; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
287 } |
72 | 288 memcpy(p, orig + last, f->start - last); |
289 p += f->start - last; | |
290 memcpy(p, f->data, f->len); | |
291 last = f->end; | |
292 p += f->len; | |
293 f++; | |
294 } | |
295 memcpy(p, orig + last, len - last); | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
296 return 1; |
72 | 297 } |
298 | |
299 /* recursively generate a patch of all bins between start and end */ | |
300 static struct flist *fold(PyObject *bins, int start, int end) | |
301 { | |
302 int len; | |
303 | |
304 if (start + 1 == end) { | |
305 /* trivial case, output a decoded list */ | |
306 PyObject *tmp = PyList_GetItem(bins, start); | |
128 | 307 if (!tmp) |
308 return NULL; | |
72 | 309 return decode(PyString_AsString(tmp), PyString_Size(tmp)); |
310 } | |
311 | |
312 /* divide and conquer, memory management is elsewhere */ | |
313 len = (end - start) / 2; | |
314 return combine(fold(bins, start, start + len), | |
315 fold(bins, start + len, end)); | |
316 } | |
317 | |
318 static PyObject * | |
319 patches(PyObject *self, PyObject *args) | |
320 { | |
321 PyObject *text, *bins, *result; | |
322 struct flist *patch; | |
323 char *in, *out; | |
324 int len, outlen; | |
325 | |
128 | 326 if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins)) |
72 | 327 return NULL; |
328 | |
329 len = PyList_Size(bins); | |
330 if (!len) { | |
331 /* nothing to do */ | |
332 Py_INCREF(text); | |
333 return text; | |
334 } | |
335 | |
336 patch = fold(bins, 0, len); | |
128 | 337 if (!patch) |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
338 return NULL; |
128 | 339 |
72 | 340 outlen = calcsize(PyString_Size(text), patch); |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
341 if (outlen < 0) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
342 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
343 goto cleanup; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
344 } |
72 | 345 result = PyString_FromStringAndSize(NULL, outlen); |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
346 if (!result) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
347 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
348 goto cleanup; |
128 | 349 } |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
350 in = PyString_AsString(text); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
351 out = PyString_AsString(result); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
352 if (!apply(out, in, PyString_Size(text), patch)) { |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
353 Py_DECREF(result); |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
354 result = NULL; |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
355 } |
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
356 cleanup: |
72 | 357 lfree(patch); |
358 return result; | |
359 } | |
360 | |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
361 /* calculate size of a patched file directly */ |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
362 static PyObject * |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
363 patchedsize(PyObject *self, PyObject *args) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
364 { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
365 long orig, start, end, len, outlen = 0, last = 0; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
366 int patchlen; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
367 char *bin, *binend; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
368 char decode[12]; /* for dealing with alignment issues */ |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
369 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
370 if (!PyArg_ParseTuple(args, "ls#", &orig, &bin, &patchlen)) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
371 return NULL; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
372 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
373 binend = bin + patchlen; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
374 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
375 while (bin < binend) { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
376 memcpy(decode, bin, 12); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
377 start = ntohl(*(uint32_t *)decode); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
378 end = ntohl(*(uint32_t *)(decode + 4)); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
379 len = ntohl(*(uint32_t *)(decode + 8)); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
380 bin += 12 + len; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
381 outlen += start - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
382 last = end; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
383 outlen += len; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
384 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
385 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
386 if (bin != binend) { |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
387 if (!PyErr_Occurred()) |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
388 PyErr_SetString(mpatch_Error, "patch cannot be decoded"); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
389 return NULL; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
390 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
391 |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
392 outlen += orig - last; |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
393 return Py_BuildValue("l", outlen); |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
394 } |
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
395 |
72 | 396 static PyMethodDef methods[] = { |
397 {"patches", patches, METH_VARARGS, "apply a series of patches\n"}, | |
2078
441ea218414e
Fill in the uncompressed size during revlog.addgroup
mason@suse.com
parents:
1978
diff
changeset
|
398 {"patchedsize", patchedsize, METH_VARARGS, "calculed patched size\n"}, |
72 | 399 {NULL, NULL} |
400 }; | |
401 | |
402 PyMODINIT_FUNC | |
403 initmpatch(void) | |
404 { | |
405 Py_InitModule3("mpatch", methods, mpatch_doc); | |
1722
681c5c211b92
catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
597
diff
changeset
|
406 mpatch_Error = PyErr_NewException("mpatch.mpatchError", NULL, NULL); |
72 | 407 } |
408 |