Success build TortoiseMerge.
[TortoiseGit.git] / src / TortoiseMerge / libsvn_diff / checksum.c
blob4d1f5bb4fd21a2bf6b046b85bfc1fb647a8adc87
1 /*
2 * checksum.c: checksum routines
4 * ====================================================================
5 * Copyright (c) 2008 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
20 #include <ctype.h>
22 #include <apr_md5.h>
23 #include <apr_sha1.h>
25 #include "svn_checksum.h"
26 #include "svn_error.h"
28 #include "sha1.h"
29 #include "md5.h"
33 /* Returns the digest size of it's argument. */
34 #define DIGESTSIZE(k) ((k) == svn_checksum_md5 ? APR_MD5_DIGESTSIZE : \
35 (k) == svn_checksum_sha1 ? APR_SHA1_DIGESTSIZE : 0)
38 /* Check to see if KIND is something we recognize. If not, return
39 * SVN_ERR_BAD_CHECKSUM_KIND */
40 static svn_error_t *
41 validate_kind(svn_checksum_kind_t kind)
43 if (kind == svn_checksum_md5 || kind == svn_checksum_sha1)
44 return SVN_NO_ERROR;
45 else
46 return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
50 svn_checksum_t *
51 svn_checksum_create(svn_checksum_kind_t kind,
52 apr_pool_t *pool)
54 svn_checksum_t *checksum;
56 switch (kind)
58 case svn_checksum_md5:
59 case svn_checksum_sha1:
60 checksum = apr_pcalloc(pool, sizeof(*checksum) + DIGESTSIZE(kind));
61 checksum->digest = (unsigned char *)checksum + sizeof(*checksum);
62 checksum->kind = kind;
63 return checksum;
65 default:
66 return NULL;
70 svn_checksum_t *
71 svn_checksum__from_digest(const unsigned char *digest,
72 svn_checksum_kind_t kind,
73 apr_pool_t *result_pool)
75 svn_checksum_t *checksum = svn_checksum_create(kind, result_pool);
77 memcpy((unsigned char *)checksum->digest, digest, DIGESTSIZE(kind));
78 return checksum;
81 svn_error_t *
82 svn_checksum_clear(svn_checksum_t *checksum)
84 SVN_ERR(validate_kind(checksum->kind));
86 memset((unsigned char *) checksum->digest, 0, DIGESTSIZE(checksum->kind));
87 return SVN_NO_ERROR;
90 svn_boolean_t
91 svn_checksum_match(const svn_checksum_t *checksum1,
92 const svn_checksum_t *checksum2)
94 if (checksum1 == NULL || checksum2 == NULL)
95 return TRUE;
97 if (checksum1->kind != checksum2->kind)
98 return FALSE;
100 switch (checksum1->kind)
102 case svn_checksum_md5:
103 return svn_md5__digests_match(checksum1->digest, checksum2->digest);
104 case svn_checksum_sha1:
105 return svn_sha1__digests_match(checksum1->digest, checksum2->digest);
106 default:
107 /* We really shouldn't get here, but if we do... */
108 return FALSE;
112 const char *
113 svn_checksum_to_cstring_display(const svn_checksum_t *checksum,
114 apr_pool_t *pool)
116 switch (checksum->kind)
118 case svn_checksum_md5:
119 return svn_md5__digest_to_cstring_display(checksum->digest, pool);
120 case svn_checksum_sha1:
121 return svn_sha1__digest_to_cstring_display(checksum->digest, pool);
122 default:
123 /* We really shouldn't get here, but if we do... */
124 return NULL;
128 const char *
129 svn_checksum_to_cstring(const svn_checksum_t *checksum,
130 apr_pool_t *pool)
132 switch (checksum->kind)
134 case svn_checksum_md5:
135 return svn_md5__digest_to_cstring(checksum->digest, pool);
136 case svn_checksum_sha1:
137 return svn_sha1__digest_to_cstring(checksum->digest, pool);
138 default:
139 /* We really shouldn't get here, but if we do... */
140 return NULL;
144 svn_error_t *
145 svn_checksum_parse_hex(svn_checksum_t **checksum,
146 svn_checksum_kind_t kind,
147 const char *hex,
148 apr_pool_t *pool)
150 int len;
151 int i;
152 unsigned char is_zeros = '\0';
154 if (hex == NULL)
156 *checksum = NULL;
157 return SVN_NO_ERROR;
160 SVN_ERR(validate_kind(kind));
162 *checksum = svn_checksum_create(kind, pool);
163 len = DIGESTSIZE(kind);
165 for (i = 0; i < len; i++)
167 if ((! isxdigit(hex[i * 2])) || (! isxdigit(hex[i * 2 + 1])))
168 return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL);
170 ((unsigned char *)(*checksum)->digest)[i] =
171 (( isalpha(hex[i*2]) ? hex[i*2] - 'a' + 10 : hex[i*2] - '0') << 4) |
172 ( isalpha(hex[i*2+1]) ? hex[i*2+1] - 'a' + 10 : hex[i*2+1] - '0');
173 is_zeros |= (*checksum)->digest[i];
176 if (is_zeros == '\0')
177 *checksum = NULL;
179 return SVN_NO_ERROR;
182 svn_checksum_t *
183 svn_checksum_dup(const svn_checksum_t *checksum,
184 apr_pool_t *pool)
186 /* The duplicate of a NULL checksum is a NULL... */
187 if (checksum == NULL)
188 return NULL;
190 return svn_checksum__from_digest(checksum->digest, checksum->kind, pool);
193 svn_error_t *
194 svn_checksum(svn_checksum_t **checksum,
195 svn_checksum_kind_t kind,
196 const void *data,
197 apr_size_t len,
198 apr_pool_t *pool)
200 apr_sha1_ctx_t sha1_ctx;
202 SVN_ERR(validate_kind(kind));
203 *checksum = svn_checksum_create(kind, pool);
205 switch (kind)
207 case svn_checksum_md5:
208 apr_md5((unsigned char *)(*checksum)->digest, data, len);
209 break;
211 case svn_checksum_sha1:
212 apr_sha1_init(&sha1_ctx);
213 apr_sha1_update(&sha1_ctx, data, len);
214 apr_sha1_final((unsigned char *)(*checksum)->digest, &sha1_ctx);
215 break;
217 default:
218 /* We really shouldn't get here, but if we do... */
219 return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
222 return SVN_NO_ERROR;
226 svn_checksum_t *
227 svn_checksum_empty_checksum(svn_checksum_kind_t kind,
228 apr_pool_t *pool)
230 const unsigned char *digest;
232 switch (kind)
234 case svn_checksum_md5:
235 digest = svn_md5__empty_string_digest();
236 break;
238 case svn_checksum_sha1:
239 digest = svn_sha1__empty_string_digest();
240 break;
242 default:
243 /* We really shouldn't get here, but if we do... */
244 return NULL;
247 return svn_checksum__from_digest(digest, kind, pool);
250 struct svn_checksum_ctx_t
252 void *apr_ctx;
253 svn_checksum_kind_t kind;
256 svn_checksum_ctx_t *
257 svn_checksum_ctx_create(svn_checksum_kind_t kind,
258 apr_pool_t *pool)
260 svn_checksum_ctx_t *ctx = apr_palloc(pool, sizeof(*ctx));
262 ctx->kind = kind;
263 switch (kind)
265 case svn_checksum_md5:
266 ctx->apr_ctx = apr_palloc(pool, sizeof(apr_md5_ctx_t));
267 apr_md5_init(ctx->apr_ctx);
268 break;
270 case svn_checksum_sha1:
271 ctx->apr_ctx = apr_palloc(pool, sizeof(apr_sha1_ctx_t));
272 apr_sha1_init(ctx->apr_ctx);
273 break;
275 default:
276 return NULL;
279 return ctx;
282 svn_error_t *
283 svn_checksum_update(svn_checksum_ctx_t *ctx,
284 const void *data,
285 apr_size_t len)
287 switch (ctx->kind)
289 case svn_checksum_md5:
290 apr_md5_update(ctx->apr_ctx, data, len);
291 break;
293 case svn_checksum_sha1:
294 apr_sha1_update(ctx->apr_ctx, data, len);
295 break;
297 default:
298 /* We really shouldn't get here, but if we do... */
299 return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
302 return SVN_NO_ERROR;
305 svn_error_t *
306 svn_checksum_final(svn_checksum_t **checksum,
307 const svn_checksum_ctx_t *ctx,
308 apr_pool_t *pool)
310 *checksum = svn_checksum_create(ctx->kind, pool);
312 switch (ctx->kind)
314 case svn_checksum_md5:
315 apr_md5_final((unsigned char *)(*checksum)->digest, ctx->apr_ctx);
316 break;
318 case svn_checksum_sha1:
319 apr_sha1_final((unsigned char *)(*checksum)->digest, ctx->apr_ctx);
320 break;
322 default:
323 /* We really shouldn't get here, but if we do... */
324 return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
327 return SVN_NO_ERROR;
330 apr_size_t
331 svn_checksum_size(const svn_checksum_t *checksum)
333 return DIGESTSIZE(checksum->kind);