003 File Manager
Current Path:
/usr/src/contrib/subversion/subversion/libsvn_subr
usr
/
src
/
contrib
/
subversion
/
subversion
/
libsvn_subr
/
📁
..
📄
adler32.c
(3.16 KB)
📄
atomic.c
(7.23 KB)
📄
auth.c
(32.4 KB)
📄
auth.h
(6.1 KB)
📄
base64.c
(19.18 KB)
📄
bit_array.c
(6.26 KB)
📄
cache-inprocess.c
(21.2 KB)
📄
cache-membuffer.c
(116.43 KB)
📄
cache-memcache.c
(17.35 KB)
📄
cache-null.c
(4.35 KB)
📄
cache.c
(10.22 KB)
📄
cache.h
(4.03 KB)
📄
cache_config.c
(6.01 KB)
📄
checksum.c
(24.17 KB)
📄
checksum.h
(2.32 KB)
📄
cmdline.c
(58.99 KB)
📄
compat.c
(5.28 KB)
📄
compress_lz4.c
(4.51 KB)
📄
compress_zlib.c
(6.85 KB)
📄
config.c
(39.66 KB)
📄
config_auth.c
(8.65 KB)
📄
config_file.c
(70.25 KB)
📄
config_impl.h
(6.15 KB)
📄
config_keys.inc
(2.65 KB)
📄
config_win.c
(9.61 KB)
📄
crypto.c
(25.19 KB)
📄
crypto.h
(5.43 KB)
📄
ctype.c
(13.81 KB)
📄
date.c
(12.86 KB)
📄
debug.c
(3.77 KB)
📄
deprecated.c
(64.3 KB)
📄
dirent_uri.c
(80.17 KB)
📄
dirent_uri.h
(1.43 KB)
📄
dso.c
(3.74 KB)
📄
encode.c
(2.69 KB)
📄
eol.c
(2.79 KB)
📄
error.c
(24.52 KB)
📄
errorcode.inc
(4.27 KB)
📄
fnv1a.c
(6.92 KB)
📄
fnv1a.h
(3.04 KB)
📄
genctype.py
(3.84 KB)
📄
gpg_agent.c
(22.29 KB)
📄
hash.c
(19.59 KB)
📄
internal_statements.h
(1.87 KB)
📄
internal_statements.sql
(1.58 KB)
📄
io.c
(182.6 KB)
📄
iter.c
(3.84 KB)
📄
libsvn_subr.pc.in
(515 B)
📄
lock.c
(1.69 KB)
📄
log.c
(14 KB)
📁
lz4
📄
macos_keychain.c
(9.7 KB)
📄
magic.c
(5.25 KB)
📄
md5.c
(1.8 KB)
📄
mergeinfo.c
(89.24 KB)
📄
mutex.c
(3.06 KB)
📄
nls.c
(3.06 KB)
📄
object_pool.c
(9.76 KB)
📄
opt.c
(39.34 KB)
📄
opt.h
(1.89 KB)
📄
packed_data.c
(33.43 KB)
📄
path.c
(35.99 KB)
📄
pool.c
(4.35 KB)
📄
pools.h
(1.45 KB)
📄
prefix_string.c
(10.65 KB)
📄
prompt.c
(28.82 KB)
📄
properties.c
(13.59 KB)
📄
quoprint.c
(8.96 KB)
📄
root_pools.c
(3.15 KB)
📄
simple_providers.c
(25.54 KB)
📄
skel.c
(23.04 KB)
📄
sorts.c
(15.9 KB)
📄
spillbuf.c
(19.78 KB)
📄
sqlite.c
(49.68 KB)
📄
sqlite3wrapper.c
(3.16 KB)
📄
ssl_client_cert_providers.c
(6.66 KB)
📄
ssl_client_cert_pw_providers.c
(18.93 KB)
📄
ssl_server_trust_providers.c
(7.77 KB)
📄
stream.c
(65.69 KB)
📄
string.c
(40.2 KB)
📄
subst.c
(67.57 KB)
📄
sysinfo.c
(43.67 KB)
📄
sysinfo.h
(2.58 KB)
📄
target.c
(11.58 KB)
📄
temp_serializer.c
(14.02 KB)
📄
time.c
(9.08 KB)
📄
token.c
(2.58 KB)
📄
types.c
(9.43 KB)
📄
user.c
(2.66 KB)
📄
username_providers.c
(9.2 KB)
📄
utf.c
(40.38 KB)
📁
utf8proc
📄
utf8proc.c
(20.71 KB)
📄
utf_validate.c
(13.3 KB)
📄
utf_width.c
(10.85 KB)
📄
validate.c
(3.35 KB)
📄
version.c
(9.89 KB)
📄
win32_crashrpt.c
(25.06 KB)
📄
win32_crashrpt.h
(1.35 KB)
📄
win32_crashrpt_dll.h
(4 KB)
📄
win32_crypto.c
(18.12 KB)
📄
win32_xlate.c
(7.3 KB)
📄
win32_xlate.h
(2.11 KB)
📄
x509.h
(3.75 KB)
📄
x509info.c
(9.53 KB)
📄
x509parse.c
(35.77 KB)
📄
xml.c
(20.01 KB)
Editing: checksum.c
/* * checksum.c: checksum routines * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== */ #define APR_WANT_BYTEFUNC #include <ctype.h> #include <apr_md5.h> #include <apr_sha1.h> #include "svn_checksum.h" #include "svn_error.h" #include "svn_ctype.h" #include "svn_sorts.h" #include "checksum.h" #include "fnv1a.h" #include "private/svn_subr_private.h" #include "svn_private_config.h" /* The MD5 digest for the empty string. */ static const unsigned char md5_empty_string_digest_array[] = { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e }; /* The SHA1 digest for the empty string. */ static const unsigned char sha1_empty_string_digest_array[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 }; /* The FNV-1a digest for the empty string. */ static const unsigned char fnv1a_32_empty_string_digest_array[] = { 0x81, 0x1c, 0x9d, 0xc5 }; /* The FNV-1a digest for the empty string. */ static const unsigned char fnv1a_32x4_empty_string_digest_array[] = { 0xcd, 0x6d, 0x9a, 0x85 }; /* Digests for an empty string, indexed by checksum type */ static const unsigned char * empty_string_digests[] = { md5_empty_string_digest_array, sha1_empty_string_digest_array, fnv1a_32_empty_string_digest_array, fnv1a_32x4_empty_string_digest_array }; /* Digest sizes in bytes, indexed by checksum type */ static const apr_size_t digest_sizes[] = { APR_MD5_DIGESTSIZE, APR_SHA1_DIGESTSIZE, sizeof(apr_uint32_t), sizeof(apr_uint32_t) }; /* Checksum type prefixes used in serialized checksums. */ static const char *ckind_str[] = { "$md5 $", "$sha1$", "$fnv1$", "$fnvm$", /* ### svn_checksum_deserialize() assumes all these have the same strlen() */ }; /* Returns the digest size of it's argument. */ #define DIGESTSIZE(k) \ (((k) < svn_checksum_md5 || (k) > svn_checksum_fnv1a_32x4) ? 0 : digest_sizes[k]) /* Largest supported digest size */ #define MAX_DIGESTSIZE (MAX(APR_MD5_DIGESTSIZE,APR_SHA1_DIGESTSIZE)) const unsigned char * svn__empty_string_digest(svn_checksum_kind_t kind) { return empty_string_digests[kind]; } const char * svn__digest_to_cstring_display(const unsigned char digest[], apr_size_t digest_size, apr_pool_t *pool) { static const char *hex = "0123456789abcdef"; char *str = apr_palloc(pool, (digest_size * 2) + 1); apr_size_t i; for (i = 0; i < digest_size; i++) { str[i*2] = hex[digest[i] >> 4]; str[i*2+1] = hex[digest[i] & 0x0f]; } str[i*2] = '\0'; return str; } const char * svn__digest_to_cstring(const unsigned char digest[], apr_size_t digest_size, apr_pool_t *pool) { static const unsigned char zeros_digest[MAX_DIGESTSIZE] = { 0 }; if (memcmp(digest, zeros_digest, digest_size) != 0) return svn__digest_to_cstring_display(digest, digest_size, pool); else return NULL; } svn_boolean_t svn__digests_match(const unsigned char d1[], const unsigned char d2[], apr_size_t digest_size) { static const unsigned char zeros[MAX_DIGESTSIZE] = { 0 }; return ((memcmp(d1, d2, digest_size) == 0) || (memcmp(d2, zeros, digest_size) == 0) || (memcmp(d1, zeros, digest_size) == 0)); } /* Check to see if KIND is something we recognize. If not, return * SVN_ERR_BAD_CHECKSUM_KIND */ static svn_error_t * validate_kind(svn_checksum_kind_t kind) { if (kind >= svn_checksum_md5 && kind <= svn_checksum_fnv1a_32x4) return SVN_NO_ERROR; else return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL); } /* Create a svn_checksum_t with everything but the contents of the digest populated. */ static svn_checksum_t * checksum_create_without_digest(svn_checksum_kind_t kind, apr_size_t digest_size, apr_pool_t *pool) { /* Use apr_palloc() instead of apr_pcalloc() so that the digest * contents are only set once by the caller. */ svn_checksum_t *checksum = apr_palloc(pool, sizeof(*checksum) + digest_size); checksum->digest = (unsigned char *)checksum + sizeof(*checksum); checksum->kind = kind; return checksum; } /* Return a checksum object, allocated in POOL. The checksum will be of * type KIND and contain the given DIGEST. */ static svn_checksum_t * checksum_create(svn_checksum_kind_t kind, const unsigned char *digest, apr_pool_t *pool) { apr_size_t digest_size = DIGESTSIZE(kind); svn_checksum_t *checksum = checksum_create_without_digest(kind, digest_size, pool); memcpy((unsigned char *)checksum->digest, digest, digest_size); return checksum; } svn_checksum_t * svn_checksum_create(svn_checksum_kind_t kind, apr_pool_t *pool) { svn_checksum_t *checksum; apr_size_t digest_size; switch (kind) { case svn_checksum_md5: case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: digest_size = digest_sizes[kind]; break; default: return NULL; } checksum = checksum_create_without_digest(kind, digest_size, pool); memset((unsigned char *) checksum->digest, 0, digest_size); return checksum; } svn_checksum_t * svn_checksum__from_digest_md5(const unsigned char *digest, apr_pool_t *result_pool) { return checksum_create(svn_checksum_md5, digest, result_pool); } svn_checksum_t * svn_checksum__from_digest_sha1(const unsigned char *digest, apr_pool_t *result_pool) { return checksum_create(svn_checksum_sha1, digest, result_pool); } svn_checksum_t * svn_checksum__from_digest_fnv1a_32(const unsigned char *digest, apr_pool_t *result_pool) { return checksum_create(svn_checksum_fnv1a_32, digest, result_pool); } svn_checksum_t * svn_checksum__from_digest_fnv1a_32x4(const unsigned char *digest, apr_pool_t *result_pool) { return checksum_create(svn_checksum_fnv1a_32x4, digest, result_pool); } svn_error_t * svn_checksum_clear(svn_checksum_t *checksum) { SVN_ERR(validate_kind(checksum->kind)); memset((unsigned char *) checksum->digest, 0, DIGESTSIZE(checksum->kind)); return SVN_NO_ERROR; } svn_boolean_t svn_checksum_match(const svn_checksum_t *checksum1, const svn_checksum_t *checksum2) { if (checksum1 == NULL || checksum2 == NULL) return TRUE; if (checksum1->kind != checksum2->kind) return FALSE; switch (checksum1->kind) { case svn_checksum_md5: case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: return svn__digests_match(checksum1->digest, checksum2->digest, digest_sizes[checksum1->kind]); default: /* We really shouldn't get here, but if we do... */ return FALSE; } } const char * svn_checksum_to_cstring_display(const svn_checksum_t *checksum, apr_pool_t *pool) { switch (checksum->kind) { case svn_checksum_md5: case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: return svn__digest_to_cstring_display(checksum->digest, digest_sizes[checksum->kind], pool); default: /* We really shouldn't get here, but if we do... */ return NULL; } } const char * svn_checksum_to_cstring(const svn_checksum_t *checksum, apr_pool_t *pool) { if (checksum == NULL) return NULL; switch (checksum->kind) { case svn_checksum_md5: case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: return svn__digest_to_cstring(checksum->digest, digest_sizes[checksum->kind], pool); default: /* We really shouldn't get here, but if we do... */ return NULL; } } const char * svn_checksum_serialize(const svn_checksum_t *checksum, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { SVN_ERR_ASSERT_NO_RETURN(checksum->kind >= svn_checksum_md5 || checksum->kind <= svn_checksum_fnv1a_32x4); return apr_pstrcat(result_pool, ckind_str[checksum->kind], svn_checksum_to_cstring(checksum, scratch_pool), SVN_VA_NULL); } svn_error_t * svn_checksum_deserialize(const svn_checksum_t **checksum, const char *data, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_checksum_kind_t kind; svn_checksum_t *parsed_checksum; /* All prefixes have the same length. */ apr_size_t prefix_len = strlen(ckind_str[0]); /* "$md5 $...", "$sha1$..." or ... */ if (strlen(data) <= prefix_len) return svn_error_createf(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, _("Invalid prefix in checksum '%s'"), data); for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind) if (strncmp(ckind_str[kind], data, prefix_len) == 0) { SVN_ERR(svn_checksum_parse_hex(&parsed_checksum, kind, data + prefix_len, result_pool)); *checksum = parsed_checksum; return SVN_NO_ERROR; } return svn_error_createf(SVN_ERR_BAD_CHECKSUM_KIND, NULL, "Unknown checksum kind in '%s'", data); } svn_error_t * svn_checksum_parse_hex(svn_checksum_t **checksum, svn_checksum_kind_t kind, const char *hex, apr_pool_t *pool) { apr_size_t i, len; unsigned char is_nonzero = 0; unsigned char *digest; static const unsigned char xdigitval[256] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0-7 */ 0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 8-9 */ 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF, /* A-F */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF, /* a-f */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; if (hex == NULL) { *checksum = NULL; return SVN_NO_ERROR; } SVN_ERR(validate_kind(kind)); *checksum = svn_checksum_create(kind, pool); digest = (unsigned char *)(*checksum)->digest; len = DIGESTSIZE(kind); for (i = 0; i < len; i++) { unsigned char x1 = xdigitval[(unsigned char)hex[i * 2]]; unsigned char x2 = xdigitval[(unsigned char)hex[i * 2 + 1]]; if (x1 == 0xFF || x2 == 0xFF) return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL); digest[i] = (x1 << 4) | x2; is_nonzero |= digest[i]; } if (!is_nonzero) *checksum = NULL; return SVN_NO_ERROR; } svn_checksum_t * svn_checksum_dup(const svn_checksum_t *checksum, apr_pool_t *pool) { /* The duplicate of a NULL checksum is a NULL... */ if (checksum == NULL) return NULL; /* Without this check on valid checksum kind a NULL svn_checksum_t * pointer is returned which could cause a core dump at an * indeterminate time in the future because callers are not * expecting a NULL pointer. This commit forces an early abort() so * it's easier to track down where the issue arose. */ switch (checksum->kind) { case svn_checksum_md5: case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: return checksum_create(checksum->kind, checksum->digest, pool); default: SVN_ERR_MALFUNCTION_NO_RETURN(); break; } } svn_error_t * svn_checksum(svn_checksum_t **checksum, svn_checksum_kind_t kind, const void *data, apr_size_t len, apr_pool_t *pool) { apr_sha1_ctx_t sha1_ctx; SVN_ERR(validate_kind(kind)); *checksum = svn_checksum_create(kind, pool); switch (kind) { case svn_checksum_md5: apr_md5((unsigned char *)(*checksum)->digest, data, len); break; case svn_checksum_sha1: apr_sha1_init(&sha1_ctx); apr_sha1_update(&sha1_ctx, data, (unsigned int)len); apr_sha1_final((unsigned char *)(*checksum)->digest, &sha1_ctx); break; case svn_checksum_fnv1a_32: *(apr_uint32_t *)(*checksum)->digest = htonl(svn__fnv1a_32(data, len)); break; case svn_checksum_fnv1a_32x4: *(apr_uint32_t *)(*checksum)->digest = htonl(svn__fnv1a_32x4(data, len)); break; default: /* We really shouldn't get here, but if we do... */ return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL); } return SVN_NO_ERROR; } svn_checksum_t * svn_checksum_empty_checksum(svn_checksum_kind_t kind, apr_pool_t *pool) { switch (kind) { case svn_checksum_md5: case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: return checksum_create(kind, empty_string_digests[kind], pool); default: /* We really shouldn't get here, but if we do... */ SVN_ERR_MALFUNCTION_NO_RETURN(); } } struct svn_checksum_ctx_t { void *apr_ctx; svn_checksum_kind_t kind; }; svn_checksum_ctx_t * svn_checksum_ctx_create(svn_checksum_kind_t kind, apr_pool_t *pool) { svn_checksum_ctx_t *ctx = apr_palloc(pool, sizeof(*ctx)); ctx->kind = kind; switch (kind) { case svn_checksum_md5: ctx->apr_ctx = apr_palloc(pool, sizeof(apr_md5_ctx_t)); apr_md5_init(ctx->apr_ctx); break; case svn_checksum_sha1: ctx->apr_ctx = apr_palloc(pool, sizeof(apr_sha1_ctx_t)); apr_sha1_init(ctx->apr_ctx); break; case svn_checksum_fnv1a_32: ctx->apr_ctx = svn_fnv1a_32__context_create(pool); break; case svn_checksum_fnv1a_32x4: ctx->apr_ctx = svn_fnv1a_32x4__context_create(pool); break; default: SVN_ERR_MALFUNCTION_NO_RETURN(); } return ctx; } svn_error_t * svn_checksum_ctx_reset(svn_checksum_ctx_t *ctx) { switch (ctx->kind) { case svn_checksum_md5: memset(ctx->apr_ctx, 0, sizeof(apr_md5_ctx_t)); apr_md5_init(ctx->apr_ctx); break; case svn_checksum_sha1: memset(ctx->apr_ctx, 0, sizeof(apr_sha1_ctx_t)); apr_sha1_init(ctx->apr_ctx); break; case svn_checksum_fnv1a_32: svn_fnv1a_32__context_reset(ctx->apr_ctx); break; case svn_checksum_fnv1a_32x4: svn_fnv1a_32x4__context_reset(ctx->apr_ctx); break; default: SVN_ERR_MALFUNCTION(); } return SVN_NO_ERROR; } svn_error_t * svn_checksum_update(svn_checksum_ctx_t *ctx, const void *data, apr_size_t len) { switch (ctx->kind) { case svn_checksum_md5: apr_md5_update(ctx->apr_ctx, data, len); break; case svn_checksum_sha1: apr_sha1_update(ctx->apr_ctx, data, (unsigned int)len); break; case svn_checksum_fnv1a_32: svn_fnv1a_32__update(ctx->apr_ctx, data, len); break; case svn_checksum_fnv1a_32x4: svn_fnv1a_32x4__update(ctx->apr_ctx, data, len); break; default: /* We really shouldn't get here, but if we do... */ return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL); } return SVN_NO_ERROR; } svn_error_t * svn_checksum_final(svn_checksum_t **checksum, const svn_checksum_ctx_t *ctx, apr_pool_t *pool) { *checksum = svn_checksum_create(ctx->kind, pool); switch (ctx->kind) { case svn_checksum_md5: apr_md5_final((unsigned char *)(*checksum)->digest, ctx->apr_ctx); break; case svn_checksum_sha1: apr_sha1_final((unsigned char *)(*checksum)->digest, ctx->apr_ctx); break; case svn_checksum_fnv1a_32: *(apr_uint32_t *)(*checksum)->digest = htonl(svn_fnv1a_32__finalize(ctx->apr_ctx)); break; case svn_checksum_fnv1a_32x4: *(apr_uint32_t *)(*checksum)->digest = htonl(svn_fnv1a_32x4__finalize(ctx->apr_ctx)); break; default: /* We really shouldn't get here, but if we do... */ return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL); } return SVN_NO_ERROR; } apr_size_t svn_checksum_size(const svn_checksum_t *checksum) { return DIGESTSIZE(checksum->kind); } svn_error_t * svn_checksum_mismatch_err(const svn_checksum_t *expected, const svn_checksum_t *actual, apr_pool_t *scratch_pool, const char *fmt, ...) { va_list ap; const char *desc; va_start(ap, fmt); desc = apr_pvsprintf(scratch_pool, fmt, ap); va_end(ap); return svn_error_createf(SVN_ERR_CHECKSUM_MISMATCH, NULL, _("%s:\n" " expected: %s\n" " actual: %s\n"), desc, svn_checksum_to_cstring_display(expected, scratch_pool), svn_checksum_to_cstring_display(actual, scratch_pool)); } svn_boolean_t svn_checksum_is_empty_checksum(svn_checksum_t *checksum) { /* By definition, the NULL checksum matches all others, including the empty one. */ if (!checksum) return TRUE; switch (checksum->kind) { case svn_checksum_md5: case svn_checksum_sha1: case svn_checksum_fnv1a_32: case svn_checksum_fnv1a_32x4: return svn__digests_match(checksum->digest, svn__empty_string_digest(checksum->kind), digest_sizes[checksum->kind]); default: /* We really shouldn't get here, but if we do... */ SVN_ERR_MALFUNCTION_NO_RETURN(); } } /* Checksum calculating stream wrappers. */ /* Baton used by write_handler and close_handler to calculate the checksum * and return the result to the stream creator. It accommodates the data * needed by svn_checksum__wrap_write_stream_fnv1a_32x4 as well as * svn_checksum__wrap_write_stream. */ typedef struct stream_baton_t { /* Stream we are wrapping. Forward write() and close() operations to it. */ svn_stream_t *inner_stream; /* Build the checksum data in here. */ svn_checksum_ctx_t *context; /* Write the final checksum here. May be NULL. */ svn_checksum_t **checksum; /* Copy the digest of the final checksum. May be NULL. */ unsigned char *digest; /* Allocate the resulting checksum here. */ apr_pool_t *pool; } stream_baton_t; /* Implement svn_write_fn_t. * Update checksum and pass data on to inner stream. */ static svn_error_t * write_handler(void *baton, const char *data, apr_size_t *len) { stream_baton_t *b = baton; SVN_ERR(svn_checksum_update(b->context, data, *len)); SVN_ERR(svn_stream_write(b->inner_stream, data, len)); return SVN_NO_ERROR; } /* Implement svn_close_fn_t. * Finalize checksum calculation and write results. Close inner stream. */ static svn_error_t * close_handler(void *baton) { stream_baton_t *b = baton; svn_checksum_t *local_checksum; /* Ensure we can always write to *B->CHECKSUM. */ if (!b->checksum) b->checksum = &local_checksum; /* Get the final checksum. */ SVN_ERR(svn_checksum_final(b->checksum, b->context, b->pool)); /* Extract digest, if wanted. */ if (b->digest) { apr_size_t digest_size = DIGESTSIZE((*b->checksum)->kind); memcpy(b->digest, (*b->checksum)->digest, digest_size); } /* Done here. Now, close the underlying stream as well. */ return svn_error_trace(svn_stream_close(b->inner_stream)); } /* Common constructor function for svn_checksum__wrap_write_stream and * svn_checksum__wrap_write_stream_fnv1a_32x4, taking the superset of their * respecting parameters. * * In the current usage, either CHECKSUM or DIGEST will be NULL but this * function does not enforce any such restriction. Also, the caller must * make sure that DIGEST refers to a buffer of sufficient length. */ static svn_stream_t * wrap_write_stream(svn_checksum_t **checksum, unsigned char *digest, svn_stream_t *inner_stream, svn_checksum_kind_t kind, apr_pool_t *pool) { svn_stream_t *outer_stream; stream_baton_t *baton = apr_pcalloc(pool, sizeof(*baton)); baton->inner_stream = inner_stream; baton->context = svn_checksum_ctx_create(kind, pool); baton->checksum = checksum; baton->digest = digest; baton->pool = pool; outer_stream = svn_stream_create(baton, pool); svn_stream_set_write(outer_stream, write_handler); svn_stream_set_close(outer_stream, close_handler); return outer_stream; } svn_stream_t * svn_checksum__wrap_write_stream(svn_checksum_t **checksum, svn_stream_t *inner_stream, svn_checksum_kind_t kind, apr_pool_t *pool) { return wrap_write_stream(checksum, NULL, inner_stream, kind, pool); } /* Implement svn_close_fn_t. * For FNV-1a-like checksums, we want the checksum as 32 bit integer instead * of a big endian 4 byte sequence. This simply wraps close_handler adding * the digest conversion. */ static svn_error_t * close_handler_fnv1a_32x4(void *baton) { stream_baton_t *b = baton; SVN_ERR(close_handler(baton)); *(apr_uint32_t *)b->digest = ntohl(*(apr_uint32_t *)b->digest); return SVN_NO_ERROR; } svn_stream_t * svn_checksum__wrap_write_stream_fnv1a_32x4(apr_uint32_t *digest, svn_stream_t *inner_stream, apr_pool_t *pool) { svn_stream_t *result = wrap_write_stream(NULL, (unsigned char *)digest, inner_stream, svn_checksum_fnv1a_32x4, pool); svn_stream_set_close(result, close_handler_fnv1a_32x4); return result; }
Upload File
Create Folder