You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/04/23 14:33:03 UTC
svn commit: r1329209 [20/38] - in /subversion/branches/javahl-ra: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/client-side/emacs/ contrib/client-side/vim/
contrib/server-side/mod_dontdothat/ notes/ notes/a...
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/cache-inprocess.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/cache-inprocess.c Mon Apr 23 12:32:48 2012
@@ -201,7 +201,7 @@ inprocess_cache_get_internal(char **buff
*size = entry->size;
}
-
+
return SVN_NO_ERROR;
}
@@ -213,16 +213,17 @@ inprocess_cache_get(void **value_p,
apr_pool_t *result_pool)
{
inprocess_cache_t *cache = cache_void;
- char* buffer;
+ char* buffer = NULL;
apr_size_t size;
- SVN_MUTEX__WITH_LOCK(cache->mutex,
- inprocess_cache_get_internal(&buffer,
- &size,
- cache,
- key,
- result_pool));
-
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_internal(&buffer,
+ &size,
+ cache,
+ key,
+ result_pool));
+
/* deserialize the buffer content. Usually, this will directly
modify the buffer content directly.
*/
@@ -303,7 +304,7 @@ inprocess_cache_set_internal(inprocess_c
cache->data_size -= existing_entry->size;
if (value)
{
- SVN_ERR(cache->serialize_func((char **)&existing_entry->value,
+ SVN_ERR(cache->serialize_func(&existing_entry->value,
&existing_entry->size,
value,
page->page_pool));
@@ -355,7 +356,7 @@ inprocess_cache_set_internal(inprocess_c
new_entry->key = duplicate_key(cache, key, page->page_pool);
if (value)
{
- SVN_ERR(cache->serialize_func((char **)&new_entry->value,
+ SVN_ERR(cache->serialize_func(&new_entry->value,
&new_entry->size,
value,
page->page_pool));
@@ -400,11 +401,12 @@ inprocess_cache_set(void *cache_void,
{
inprocess_cache_t *cache = cache_void;
- SVN_MUTEX__WITH_LOCK(cache->mutex,
- inprocess_cache_set_internal(cache,
- key,
- value,
- scratch_pool));
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_set_internal(cache,
+ key,
+ value,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -443,7 +445,7 @@ inprocess_cache_iter(svn_boolean_t *comp
b.user_baton = user_baton;
SVN_MUTEX__WITH_LOCK(cache->mutex,
- svn_iter_apr_hash(completed, cache->hash,
+ svn_iter_apr_hash(completed, cache->hash,
iter_cb, &b, scratch_pool));
return SVN_NO_ERROR;
@@ -482,14 +484,17 @@ inprocess_cache_get_partial(void **value
{
inprocess_cache_t *cache = cache_void;
- SVN_MUTEX__WITH_LOCK(cache->mutex,
- inprocess_cache_get_partial_internal(value_p,
- found,
- cache,
- key,
- func,
- baton,
- result_pool));
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_partial_internal(value_p,
+ found,
+ cache,
+ key,
+ func,
+ baton,
+ result_pool));
+ else
+ *found = FALSE;
return SVN_NO_ERROR;
}
@@ -507,10 +512,10 @@ inprocess_cache_set_partial_internal(inp
SVN_ERR(move_page_to_front(cache, entry->page));
cache->data_size -= entry->size;
- SVN_ERR(func((char **)&entry->value,
- &entry->size,
- baton,
- entry->page->page_pool));
+ SVN_ERR(func(&entry->value,
+ &entry->size,
+ baton,
+ entry->page->page_pool));
cache->data_size += entry->size;
}
@@ -526,12 +531,13 @@ inprocess_cache_set_partial(void *cache_
{
inprocess_cache_t *cache = cache_void;
- SVN_MUTEX__WITH_LOCK(cache->mutex,
- inprocess_cache_set_partial_internal(cache,
- key,
- func,
- baton,
- scratch_pool));
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_set_partial_internal(cache,
+ key,
+ func,
+ baton,
+ scratch_pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/cache-membuffer.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/cache-membuffer.c Mon Apr 23 12:32:48 2012
@@ -136,6 +136,13 @@
*/
#define NO_OFFSET APR_UINT64_MAX
+/* To save space in our group structure, we only use 32 bit size values
+ * and, therefore, limit the size of each entry to just below 4GB.
+ * Supporting larger items is not a good idea as the data transfer
+ * to and from the cache would block other threads for a very long time.
+ */
+#define MAX_ITEM_SIZE ((apr_uint32_t)(0 - ITEM_ALIGNMENT))
+
/* Debugging / corruption detection support.
* If you define this macro, the getter functions will performed expensive
* checks on the item data, requested keys and entry types. If there is
@@ -304,7 +311,7 @@ typedef struct entry_t
/* Size of the serialized item data. May be 0.
* Only valid for used entries.
*/
- apr_uint32_t size;
+ apr_size_t size;
/* Number of (read) hits for this entry. Will be reset upon write.
* Only valid for used entries.
@@ -395,6 +402,11 @@ struct svn_membuffer_t
*/
apr_uint64_t data_used;
+ /* Largest entry size that we would accept. For total cache sizes
+ * less than 4TB (sic!), this is determined by the total cache size.
+ */
+ apr_uint64_t max_entry_size;
+
/* Number of used dictionary entries, i.e. number of cached items.
* In conjunction with hit_count, this is used calculate the average
@@ -572,40 +584,25 @@ insert_entry(svn_membuffer_t *cache, ent
}
}
-/* Map a KEY of length LEN to the CACHE and group that shall contain the
- * respective item. Return the hash value in TO_FIND. Returns -1 upon error.
+/* Map a KEY of 16 bytes to the CACHE and group that shall contain the
+ * respective item.
*/
static apr_uint32_t
get_group_index(svn_membuffer_t **cache,
- const void *key,
- apr_size_t len,
- unsigned char *to_find,
- apr_pool_t *pool)
+ const apr_uint32_t *key)
{
- apr_uint32_t hash = 0;
- int i;
-
- /* calculate a hash value for the key */
- svn_checksum_t *checksum;
- svn_error_t *err;
-
- err = svn_checksum(&checksum, svn_checksum_md5, key, len, pool);
- if (err != NULL)
- {
- svn_error_clear(err);
- return NO_INDEX;
- }
-
- memcpy(to_find, checksum->digest, APR_MD5_DIGESTSIZE);
-
- /* select the cache segment to use */
- *cache = &(*cache)[to_find[0] & ((*cache)->segment_count -1)];
+ apr_uint32_t hash;
/* Get the group that *must* contain the entry. Fold the hash value
* just to be sure (it should not be necessary for perfect hashes).
*/
- for (i = 0; i < sizeof(to_find) / sizeof(apr_uint32_t); ++i)
- hash += ((apr_uint32_t*)to_find)[i] ^ ((hash >> 19) || (hash << 13));
+ hash = key[0];
+ hash = key[1] ^ ((hash >> 19) || (hash << 13));
+ hash = key[2] ^ ((hash >> 19) || (hash << 13));
+ hash = key[3] ^ ((hash >> 19) || (hash << 13));
+
+ /* select the cache segment to use */
+ *cache = &(*cache)[key[0] & ((*cache)->segment_count -1)];
return hash % (*cache)->group_count;
}
@@ -946,6 +943,7 @@ svn_cache__membuffer_cache_create(svn_me
apr_uint32_t group_count;
apr_uint32_t group_init_size;
apr_uint64_t data_size;
+ apr_uint64_t max_entry_size;
/* Determine a reasonable number of cache segments. Segmentation is
* only useful for multi-threaded / multi-core servers as it reduces
@@ -989,8 +987,19 @@ svn_cache__membuffer_cache_create(svn_me
*/
data_size = total_size - directory_size;
+ /* For cache sizes > 4TB, individual cache segments will be larger
+ * than 16GB allowing for >4GB entries. But caching chunks larger
+ * than 4GB is simply not supported.
+ */
+ max_entry_size = data_size / 4 > MAX_ITEM_SIZE
+ ? MAX_ITEM_SIZE
+ : data_size / 4;
+
/* to keep the entries small, we use 32 bit indices only
- * -> we need to ensure that no more then 4G entries exist
+ * -> we need to ensure that no more then 4G entries exist.
+ *
+ * Note, that this limit could only be exceeded in a very
+ * theoretical setup with about 1EB of cache.
*/
group_count = directory_size / sizeof(entry_group_t);
if (group_count >= (APR_UINT32_MAX / GROUP_SIZE))
@@ -1021,6 +1030,7 @@ svn_cache__membuffer_cache_create(svn_me
c[seg].data = secure_aligned_alloc(pool, (apr_size_t)data_size, FALSE);
c[seg].current_data = 0;
c[seg].data_used = 0;
+ c[seg].max_entry_size = max_entry_size;
c[seg].used_entries = 0;
c[seg].hit_count = 0;
@@ -1052,14 +1062,14 @@ svn_cache__membuffer_cache_create(svn_me
/* Try to insert the serialized item given in BUFFER with SIZE into
- * the group GROUP_INDEX of CACHE and uniquely identify it by hash
- * value TO_FIND.
- *
+ * the group GROUP_INDEX of CACHE and uniquely identify it by hash
+ * value TO_FIND.
+ *
* However, there is no guarantee that it will actually be put into
* the cache. If there is already some data associated with TO_FIND,
* it will be removed from the cache even if the new data cannot
* be inserted.
- *
+ *
* Note: This function requires the caller to serialization access.
* Don't call it directly, call membuffer_cache_get_partial instead.
*/
@@ -1075,7 +1085,7 @@ membuffer_cache_set_internal(svn_membuff
/* if necessary, enlarge the insertion window.
*/
if ( buffer != NULL
- && cache->data_size / 4 > size
+ && cache->max_entry_size >= size
&& ensure_data_insertable(cache, size))
{
/* Remove old data for this key, if that exists.
@@ -1126,22 +1136,18 @@ membuffer_cache_set_internal(svn_membuff
static svn_error_t *
membuffer_cache_set(svn_membuffer_t *cache,
const void *key,
- apr_size_t key_len,
void *item,
svn_cache__serialize_func_t serializer,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *scratch_pool)
{
apr_uint32_t group_index;
- unsigned char to_find[KEY_SIZE];
- char *buffer = NULL;
- apr_size_t size;
+ void *buffer = NULL;
+ apr_size_t size = 0;
/* find the entry group that will hold the key.
*/
- group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
- if (group_index == NO_INDEX)
- return SVN_NO_ERROR;
+ group_index = get_group_index(&cache, key);
/* Serialize data data.
*/
@@ -1152,7 +1158,7 @@ membuffer_cache_set(svn_membuffer_t *cac
*/
SVN_MUTEX__WITH_LOCK(cache->mutex,
membuffer_cache_set_internal(cache,
- to_find,
+ key,
group_index,
buffer,
size,
@@ -1162,11 +1168,11 @@ membuffer_cache_set(svn_membuffer_t *cac
}
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
- * by the hash value TO_FIND. If no item has been stored for KEY,
+ * by the hash value TO_FIND. If no item has been stored for KEY,
* *BUFFER will be NULL. Otherwise, return a copy of the serialized
- * data in *BUFFER and return its size in *ITEM_SIZE. Allocations will
+ * data in *BUFFER and return its size in *ITEM_SIZE. Allocations will
* be done in POOL.
- *
+ *
* Note: This function requires the caller to serialization access.
* Don't call it directly, call membuffer_cache_get_partial instead.
*/
@@ -1192,10 +1198,10 @@ membuffer_cache_get_internal(svn_membuff
*/
*buffer = NULL;
*item_size = 0;
-
+
return SVN_NO_ERROR;
}
-
+
size = ALIGN_VALUE(entry->size);
*buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
memcpy(*buffer, (const char*)cache->data + entry->offset, size);
@@ -1222,7 +1228,7 @@ membuffer_cache_get_internal(svn_membuff
cache->total_hits++;
*item_size = entry->size;
-
+
return SVN_NO_ERROR;
}
@@ -1234,32 +1240,22 @@ membuffer_cache_get_internal(svn_membuff
static svn_error_t *
membuffer_cache_get(svn_membuffer_t *cache,
const void *key,
- apr_size_t key_len,
void **item,
svn_cache__deserialize_func_t deserializer,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *result_pool)
{
apr_uint32_t group_index;
- unsigned char to_find[KEY_SIZE];
char *buffer;
apr_size_t size;
/* find the entry group that will hold the key.
*/
- group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
- if (group_index == NO_INDEX)
- {
- /* Some error occured, return "item not found".
- */
- *item = NULL;
- return SVN_NO_ERROR;
- }
-
+ group_index = get_group_index(&cache, key);
SVN_MUTEX__WITH_LOCK(cache->mutex,
membuffer_cache_get_internal(cache,
group_index,
- to_find,
+ key,
&buffer,
&size,
DEBUG_CACHE_MEMBUFFER_TAG
@@ -1272,18 +1268,18 @@ membuffer_cache_get(svn_membuffer_t *cac
*item = NULL;
return SVN_NO_ERROR;
}
-
+
return deserializer(item, buffer, size, result_pool);
}
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
* by the hash value TO_FIND. FOUND indicates whether that entry exists.
* If not found, *ITEM will be NULL.
- *
- * Otherwise, the DESERIALIZER is called with that entry and the BATON
+ *
+ * Otherwise, the DESERIALIZER is called with that entry and the BATON
* provided and will extract the desired information. The result is set
* in *ITEM. Allocations will be done in POOL.
- *
+ *
* Note: This function requires the caller to serialization access.
* Don't call it directly, call membuffer_cache_get_partial instead.
*/
@@ -1304,7 +1300,7 @@ membuffer_cache_get_partial_internal(svn
{
*item = NULL;
*found = FALSE;
-
+
return SVN_NO_ERROR;
}
else
@@ -1341,7 +1337,7 @@ membuffer_cache_get_partial_internal(svn
}
}
-/* Look for the cache entry identified by KEY and KEY_LEN. FOUND indicates
+/* Look for the cache entry identified by KEY. FOUND indicates
* whether that entry exists. If not found, *ITEM will be NULL. Otherwise,
* the DESERIALIZER is called with that entry and the BATON provided
* and will extract the desired information. The result is set in *ITEM.
@@ -1350,7 +1346,6 @@ membuffer_cache_get_partial_internal(svn
static svn_error_t *
membuffer_cache_get_partial(svn_membuffer_t *cache,
const void *key,
- apr_size_t key_len,
void **item,
svn_boolean_t *found,
svn_cache__partial_getter_func_t deserializer,
@@ -1358,14 +1353,11 @@ membuffer_cache_get_partial(svn_membuffe
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *result_pool)
{
- apr_uint32_t group_index;
- unsigned char to_find[KEY_SIZE];
-
- group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
+ apr_uint32_t group_index = get_group_index(&cache, key);
SVN_MUTEX__WITH_LOCK(cache->mutex,
membuffer_cache_get_partial_internal
- (cache, group_index, to_find, item, found,
+ (cache, group_index, key, item, found,
deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
result_pool));
@@ -1375,10 +1367,10 @@ membuffer_cache_get_partial(svn_membuffe
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
* by the hash value TO_FIND. If no entry has been found, the function
* returns without modifying the cache.
- *
+ *
* Otherwise, FUNC is called with that entry and the BATON provided
* and may modify the cache entry. Allocations will be done in POOL.
- *
+ *
* Note: This function requires the caller to serialization access.
* Don't call it directly, call membuffer_cache_set_partial instead.
*/
@@ -1428,7 +1420,7 @@ membuffer_cache_set_partial_internal(svn
/* modify it, preferrably in-situ.
*/
- err = func(&data, &size, baton, scratch_pool);
+ err = func((void **)&data, &size, baton, scratch_pool);
if (err)
{
@@ -1448,7 +1440,7 @@ membuffer_cache_set_partial_internal(svn
/* Remove the old entry and try to make space for the new one.
*/
drop_entry(cache, entry);
- if ( (cache->data_size / 4 > size)
+ if ( (cache->max_entry_size >= size)
&& ensure_data_insertable(cache, size))
{
/* Write the new entry.
@@ -1478,7 +1470,7 @@ membuffer_cache_set_partial_internal(svn
return SVN_NO_ERROR;
}
-/* Look for the cache entry identified by KEY and KEY_LEN. If no entry
+/* Look for the cache entry identified by KEY. If no entry
* has been found, the function returns without modifying the cache.
* Otherwise, FUNC is called with that entry and the BATON provided
* and may modify the cache entry. Allocations will be done in POOL.
@@ -1486,22 +1478,17 @@ membuffer_cache_set_partial_internal(svn
static svn_error_t *
membuffer_cache_set_partial(svn_membuffer_t *cache,
const void *key,
- apr_size_t key_len,
svn_cache__partial_setter_func_t func,
void *baton,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *scratch_pool)
{
- apr_uint32_t group_index;
- unsigned char to_find[KEY_SIZE];
-
/* cache item lookup
*/
- group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
-
+ apr_uint32_t group_index = get_group_index(&cache, key);
SVN_MUTEX__WITH_LOCK(cache->mutex,
membuffer_cache_set_partial_internal
- (cache, group_index, to_find, func, baton,
+ (cache, group_index, key, func, baton,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
scratch_pool));
@@ -1546,7 +1533,7 @@ typedef struct svn_membuffer_cache_t
* This makes (very likely) our keys different from all keys used
* by other svn_membuffer_cache_t instances.
*/
- unsigned char prefix [APR_MD5_DIGESTSIZE];
+ apr_uint64_t prefix [APR_MD5_DIGESTSIZE / sizeof(apr_uint64_t)];
/* A copy of the unmodified prefix. It is being used as a user-visible
* ID for this cache instance.
@@ -1558,6 +1545,10 @@ typedef struct svn_membuffer_cache_t
*/
apr_ssize_t key_len;
+ /* Temporary buffer containing the hash key for the current access
+ */
+ apr_uint64_t combined_key [APR_MD5_DIGESTSIZE / sizeof(apr_uint64_t)];
+
/* a pool for temporary allocations during get() and set()
*/
apr_pool_t *pool;
@@ -1567,6 +1558,9 @@ typedef struct svn_membuffer_cache_t
*/
int alloc_counter;
+ /* if enabled, this will serialize the access to this instance.
+ */
+ svn_mutex__t *mutex;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
/* Invariant tag info for all items stored by this cache instance.
@@ -1582,29 +1576,24 @@ typedef struct svn_membuffer_cache_t
#define ALLOCATIONS_PER_POOL_CLEAR 10
-/* Basically concatenate PREFIX and KEY and return the result in FULL_KEY.
- * Allocations will be made in POOL.
+/* Basically calculate a hash value for KEY of length KEY_LEN, combine it
+ * with the CACHE->PREFIX and write the result in CACHE->COMBINED_KEY.
*/
static void
-combine_key(const void *prefix,
- apr_size_t prefix_len,
+combine_key(svn_membuffer_cache_t *cache,
const void *key,
- apr_ssize_t key_len,
- void **full_key,
- apr_size_t *full_key_len,
- apr_pool_t *pool)
+ apr_ssize_t key_len)
{
if (key_len == APR_HASH_KEY_STRING)
key_len = strlen((const char *) key);
- *full_key_len = prefix_len + key_len;
- *full_key = apr_palloc(pool, *full_key_len);
+ apr_md5((unsigned char*)cache->combined_key, key, key_len);
- memcpy(*full_key, prefix, prefix_len);
- memcpy((char *)*full_key + prefix_len, key, key_len);
+ cache->combined_key[0] ^= cache->prefix[0];
+ cache->combined_key[1] ^= cache->prefix[1];
}
-/* Implement svn_cache__vtable_t.get
+/* Implement svn_cache__vtable_t.get (not thread-safe)
*/
static svn_error_t *
svn_membuffer_cache_get(void **value_p,
@@ -1615,26 +1604,25 @@ svn_membuffer_cache_get(void **value_p,
{
svn_membuffer_cache_t *cache = cache_void;
+ DEBUG_CACHE_MEMBUFFER_INIT_TAG
+
+ /* special case */
+ if (key == NULL)
+ {
+ *value_p = NULL;
+ *found = FALSE;
+
+ return SVN_NO_ERROR;
+ }
+
/* construct the full, i.e. globally unique, key by adding
* this cache instances' prefix
*/
- void *full_key;
- apr_size_t full_key_len;
-
- DEBUG_CACHE_MEMBUFFER_INIT_TAG
-
- combine_key(cache->prefix,
- sizeof(cache->prefix),
- key,
- cache->key_len,
- &full_key,
- &full_key_len,
- cache->pool);
+ combine_key(cache, key, cache->key_len);
/* Look the item up. */
SVN_ERR(membuffer_cache_get(cache->membuffer,
- full_key,
- full_key_len,
+ cache->combined_key,
value_p,
cache->deserializer,
DEBUG_CACHE_MEMBUFFER_TAG
@@ -1655,7 +1643,7 @@ svn_membuffer_cache_get(void **value_p,
return SVN_NO_ERROR;
}
-/* Implement svn_cache__vtable_t.set
+/* Implement svn_cache__vtable_t.set (not thread-safe)
*/
static svn_error_t *
svn_membuffer_cache_set(void *cache_void,
@@ -1665,11 +1653,12 @@ svn_membuffer_cache_set(void *cache_void
{
svn_membuffer_cache_t *cache = cache_void;
- void *full_key;
- apr_size_t full_key_len;
-
DEBUG_CACHE_MEMBUFFER_INIT_TAG
+ /* special case */
+ if (key == NULL)
+ return SVN_NO_ERROR;
+
/* we do some allocations below, so increase the allocation counter
* by a slightly larger amount. Free allocated memory every now and then.
*/
@@ -1683,20 +1672,13 @@ svn_membuffer_cache_set(void *cache_void
/* construct the full, i.e. globally unique, key by adding
* this cache instances' prefix
*/
- combine_key(cache->prefix,
- sizeof(cache->prefix),
- key,
- cache->key_len,
- &full_key,
- &full_key_len,
- cache->pool);
+ combine_key(cache, key, cache->key_len);
/* (probably) add the item to the cache. But there is no real guarantee
* that the item will actually be cached afterwards.
*/
return membuffer_cache_set(cache->membuffer,
- full_key,
- full_key_len,
+ cache->combined_key,
value,
cache->serializer,
DEBUG_CACHE_MEMBUFFER_TAG
@@ -1716,7 +1698,7 @@ svn_membuffer_cache_iter(svn_boolean_t *
_("Can't iterate a membuffer-based cache"));
}
-/* Implement svn_cache__vtable_t.get_partial
+/* Implement svn_cache__vtable_t.get_partial (not thread-safe)
*/
static svn_error_t *
svn_membuffer_cache_get_partial(void **value_p,
@@ -1729,28 +1711,25 @@ svn_membuffer_cache_get_partial(void **v
{
svn_membuffer_cache_t *cache = cache_void;
- void *full_key;
- apr_size_t full_key_len;
-
DEBUG_CACHE_MEMBUFFER_INIT_TAG
+ if (key == NULL)
+ {
+ *value_p = NULL;
+ *found = FALSE;
+
+ return SVN_NO_ERROR;
+ }
+
if (++cache->alloc_counter > ALLOCATIONS_PER_POOL_CLEAR)
{
apr_pool_clear(cache->pool);
cache->alloc_counter = 0;
}
- combine_key(cache->prefix,
- sizeof(cache->prefix),
- key,
- cache->key_len,
- &full_key,
- &full_key_len,
- cache->pool);
-
+ combine_key(cache, key, cache->key_len);
SVN_ERR(membuffer_cache_get_partial(cache->membuffer,
- full_key,
- full_key_len,
+ cache->combined_key,
value_p,
found,
func,
@@ -1761,7 +1740,7 @@ svn_membuffer_cache_get_partial(void **v
return SVN_NO_ERROR;
}
-/* Implement svn_cache__vtable_t.set_partial
+/* Implement svn_cache__vtable_t.set_partial (not thread-safe)
*/
static svn_error_t *
svn_membuffer_cache_set_partial(void *cache_void,
@@ -1772,31 +1751,23 @@ svn_membuffer_cache_set_partial(void *ca
{
svn_membuffer_cache_t *cache = cache_void;
- void *full_key;
- apr_size_t full_key_len;
-
DEBUG_CACHE_MEMBUFFER_INIT_TAG
- combine_key(cache->prefix,
- sizeof(cache->prefix),
- key,
- cache->key_len,
- &full_key,
- &full_key_len,
- scratch_pool);
-
- SVN_ERR(membuffer_cache_set_partial(cache->membuffer,
- full_key,
- full_key_len,
- func,
- baton,
- DEBUG_CACHE_MEMBUFFER_TAG
- scratch_pool));
-
+ if (key != NULL)
+ {
+ combine_key(cache, key, cache->key_len);
+ SVN_ERR(membuffer_cache_set_partial(cache->membuffer,
+ cache->combined_key,
+ func,
+ baton,
+ DEBUG_CACHE_MEMBUFFER_TAG
+ scratch_pool));
+ }
return SVN_NO_ERROR;
}
/* Implement svn_cache__vtable_t.is_cachable
+ * (thread-safe even without mutex)
*/
static svn_boolean_t
svn_membuffer_cache_is_cachable(void *cache_void, apr_size_t size)
@@ -1806,8 +1777,7 @@ svn_membuffer_cache_is_cachable(void *ca
* must be small enough to be stored in a 32 bit value.
*/
svn_membuffer_cache_t *cache = cache_void;
- return (size < cache->membuffer->data_size / 4)
- && (size < APR_UINT32_MAX - ITEM_ALIGNMENT);
+ return size <= cache->membuffer->max_entry_size;
}
/* Add statistics of SEGMENT to INFO.
@@ -1828,6 +1798,7 @@ svn_membuffer_get_segment_info(svn_membu
}
/* Implement svn_cache__vtable_t.get_info
+ * (thread-safe even without mutex)
*/
static svn_error_t *
svn_membuffer_cache_get_info(void *cache_void,
@@ -1854,7 +1825,7 @@ svn_membuffer_cache_get_info(void *cache
for (i = 0; i < cache->membuffer->segment_count; ++i)
{
svn_membuffer_t *segment = cache->membuffer + i;
- SVN_MUTEX__WITH_LOCK(segment->mutex,
+ SVN_MUTEX__WITH_LOCK(segment->mutex,
svn_membuffer_get_segment_info(segment, info));
}
@@ -1862,7 +1833,7 @@ svn_membuffer_cache_get_info(void *cache
}
-/* the v-table for membuffer-based caches
+/* the v-table for membuffer-based caches (single-threaded access)
*/
static svn_cache__vtable_t membuffer_cache_vtable = {
svn_membuffer_cache_get,
@@ -1874,11 +1845,105 @@ static svn_cache__vtable_t membuffer_cac
svn_membuffer_cache_get_info
};
+/* Implement svn_cache__vtable_t.get and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_get_synced(void **value_p,
+ svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *result_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_membuffer_cache_get(value_p,
+ found,
+ cache_void,
+ key,
+ result_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.set and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_set_synced(void *cache_void,
+ const void *key,
+ void *value,
+ apr_pool_t *scratch_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_membuffer_cache_set(cache_void,
+ key,
+ value,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.get_partial and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_get_partial_synced(void **value_p,
+ svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ svn_cache__partial_getter_func_t func,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_membuffer_cache_get_partial(value_p,
+ found,
+ cache_void,
+ key,
+ func,
+ baton,
+ result_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.set_partial and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_set_partial_synced(void *cache_void,
+ const void *key,
+ svn_cache__partial_setter_func_t func,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_membuffer_cache_set_partial(cache_void,
+ key,
+ func,
+ baton,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* the v-table for membuffer-based caches with multi-threading support)
+ */
+static svn_cache__vtable_t membuffer_cache_synced_vtable = {
+ svn_membuffer_cache_get_synced,
+ svn_membuffer_cache_set_synced,
+ svn_membuffer_cache_iter, /* no sync required */
+ svn_membuffer_cache_is_cachable, /* no sync required */
+ svn_membuffer_cache_get_partial_synced,
+ svn_membuffer_cache_set_partial_synced,
+ svn_membuffer_cache_get_info /* no sync required */
+};
+
/* standard serialization function for svn_stringbuf_t items.
* Implements svn_cache__serialize_func_t.
*/
static svn_error_t *
-serialize_svn_stringbuf(char **buffer,
+serialize_svn_stringbuf(void **buffer,
apr_size_t *buffer_size,
void *item,
apr_pool_t *result_pool)
@@ -1896,12 +1961,14 @@ serialize_svn_stringbuf(char **buffer,
*/
static svn_error_t *
deserialize_svn_stringbuf(void **item,
- char *buffer,
+ void *buffer,
apr_size_t buffer_size,
apr_pool_t *result_pool)
{
- svn_string_t *value_str = apr_palloc(result_pool, sizeof(svn_string_t));
+ svn_stringbuf_t *value_str = apr_palloc(result_pool, sizeof(svn_stringbuf_t));
+ value_str->pool = result_pool;
+ value_str->blocksize = buffer_size;
value_str->data = buffer;
value_str->len = buffer_size-1;
*item = value_str;
@@ -1918,6 +1985,7 @@ svn_cache__create_membuffer_cache(svn_ca
svn_cache__deserialize_func_t deserializer,
apr_ssize_t klen,
const char *prefix,
+ svn_boolean_t thread_safe,
apr_pool_t *pool)
{
svn_checksum_t *checksum;
@@ -1941,6 +2009,8 @@ svn_cache__create_membuffer_cache(svn_ca
cache->pool = svn_pool_create(pool);
cache->alloc_counter = 0;
+ SVN_ERR(svn_mutex__init(&cache->mutex, thread_safe, pool));
+
/* for performance reasons, we don't actually store the full prefix but a
* hash value of it
*/
@@ -1961,7 +2031,8 @@ svn_cache__create_membuffer_cache(svn_ca
/* initialize the generic cache wrapper
*/
- wrapper->vtable = &membuffer_cache_vtable;
+ wrapper->vtable = thread_safe ? &membuffer_cache_synced_vtable
+ : &membuffer_cache_vtable;
wrapper->cache_internal = cache;
wrapper->error_handler = 0;
wrapper->error_baton = 0;
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/cache-memcache.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/cache-memcache.c Mon Apr 23 12:32:48 2012
@@ -141,8 +141,15 @@ memcache_internal_get(char **data,
memcache_t *cache = cache_void;
apr_status_t apr_err;
const char *mc_key;
- apr_pool_t *subpool = svn_pool_create(pool);
+ apr_pool_t *subpool;
+
+ if (key == NULL)
+ {
+ *found = FALSE;
+ return SVN_NO_ERROR;
+ }
+ subpool = svn_pool_create(pool);
SVN_ERR(build_key(&mc_key, cache, key, subpool));
apr_err = apr_memcache_getp(cache->memcache,
@@ -240,10 +247,13 @@ memcache_set(void *cache_void,
{
memcache_t *cache = cache_void;
apr_pool_t *subpool = svn_pool_create(scratch_pool);
- char *data;
+ void *data;
apr_size_t data_len;
svn_error_t *err;
+ if (key == NULL)
+ return SVN_NO_ERROR;
+
if (cache->serialize_func)
{
SVN_ERR((cache->serialize_func)(&data, &data_len, value, subpool));
@@ -297,12 +307,12 @@ memcache_set_partial(void *cache_void,
{
svn_error_t *err = SVN_NO_ERROR;
- char *data;
+ void *data;
apr_size_t size;
svn_boolean_t found = FALSE;
apr_pool_t *subpool = svn_pool_create(scratch_pool);
- SVN_ERR(memcache_internal_get(&data,
+ SVN_ERR(memcache_internal_get((char **)&data,
&size,
&found,
cache_void,
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/checksum.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/checksum.c Mon Apr 23 12:32:48 2012
@@ -34,6 +34,8 @@
#include "sha1.h"
#include "md5.h"
+#include "private/svn_subr_private.h"
+
#include "svn_private_config.h"
@@ -54,36 +56,71 @@ validate_kind(svn_checksum_kind_t kind)
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;
+}
+
+static svn_checksum_t *
+checksum_create(svn_checksum_kind_t kind,
+ apr_size_t digest_size,
+ const unsigned char *digest,
+ apr_pool_t *pool)
+{
+ 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:
+ digest_size = APR_MD5_DIGESTSIZE;
+ break;
case svn_checksum_sha1:
- checksum = apr_pcalloc(pool, sizeof(*checksum) + DIGESTSIZE(kind));
- checksum->digest = (unsigned char *)checksum + sizeof(*checksum);
- checksum->kind = kind;
- return checksum;
-
+ digest_size = APR_SHA1_DIGESTSIZE;
+ 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(const unsigned char *digest,
- svn_checksum_kind_t kind,
- apr_pool_t *result_pool)
+svn_checksum__from_digest_md5(const unsigned char *digest,
+ apr_pool_t *result_pool)
{
- svn_checksum_t *checksum = svn_checksum_create(kind, result_pool);
+ return checksum_create(svn_checksum_md5, APR_MD5_DIGESTSIZE, digest,
+ result_pool);
+}
- memcpy((unsigned char *)checksum->digest, digest, DIGESTSIZE(kind));
- return checksum;
+svn_checksum_t *
+svn_checksum__from_digest_sha1(const unsigned char *digest,
+ apr_pool_t *result_pool)
+{
+ return checksum_create(svn_checksum_sha1, APR_SHA1_DIGESTSIZE, digest,
+ result_pool);
}
svn_error_t *
@@ -160,6 +197,8 @@ svn_checksum_serialize(const svn_checksu
{
const char *ckind_str;
+ SVN_ERR_ASSERT_NO_RETURN(checksum->kind == svn_checksum_md5
+ || checksum->kind == svn_checksum_sha1);
ckind_str = (checksum->kind == svn_checksum_md5 ? "$md5 $" : "$sha1$");
return apr_pstrcat(result_pool,
ckind_str,
@@ -255,7 +294,23 @@ svn_checksum_dup(const svn_checksum_t *c
if (checksum == NULL)
return NULL;
- return svn_checksum__from_digest(checksum->digest, checksum->kind, pool);
+ /* 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:
+ return svn_checksum__from_digest_md5(checksum->digest, pool);
+ break;
+ case svn_checksum_sha1:
+ return svn_checksum__from_digest_sha1(checksum->digest, pool);
+ break;
+ default:
+ SVN_ERR_MALFUNCTION_NO_RETURN();
+ break;
+ }
}
svn_error_t *
@@ -278,7 +333,7 @@ svn_checksum(svn_checksum_t **checksum,
case svn_checksum_sha1:
apr_sha1_init(&sha1_ctx);
- apr_sha1_update(&sha1_ctx, data, len);
+ apr_sha1_update(&sha1_ctx, data, (unsigned int)len);
apr_sha1_final((unsigned char *)(*checksum)->digest, &sha1_ctx);
break;
@@ -295,24 +350,20 @@ svn_checksum_t *
svn_checksum_empty_checksum(svn_checksum_kind_t kind,
apr_pool_t *pool)
{
- const unsigned char *digest;
-
switch (kind)
{
case svn_checksum_md5:
- digest = svn_md5__empty_string_digest();
- break;
+ return svn_checksum__from_digest_md5(svn_md5__empty_string_digest(),
+ pool);
case svn_checksum_sha1:
- digest = svn_sha1__empty_string_digest();
- break;
+ return svn_checksum__from_digest_sha1(svn_sha1__empty_string_digest(),
+ pool);
default:
/* We really shouldn't get here, but if we do... */
- return NULL;
+ SVN_ERR_MALFUNCTION_NO_RETURN();
}
-
- return svn_checksum__from_digest(digest, kind, pool);
}
struct svn_checksum_ctx_t
@@ -341,7 +392,7 @@ svn_checksum_ctx_create(svn_checksum_kin
break;
default:
- return NULL;
+ SVN_ERR_MALFUNCTION_NO_RETURN();
}
return ctx;
@@ -359,7 +410,7 @@ svn_checksum_update(svn_checksum_ctx_t *
break;
case svn_checksum_sha1:
- apr_sha1_update(ctx->apr_ctx, data, len);
+ apr_sha1_update(ctx->apr_ctx, data, (unsigned int)len);
break;
default:
@@ -423,3 +474,27 @@ svn_checksum_mismatch_err(const svn_chec
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:
+ return svn_md5__digests_match(checksum->digest,
+ svn_md5__empty_string_digest());
+
+ case svn_checksum_sha1:
+ return svn_sha1__digests_match(checksum->digest,
+ svn_sha1__empty_string_digest());
+
+ default:
+ /* We really shouldn't get here, but if we do... */
+ SVN_ERR_MALFUNCTION_NO_RETURN();
+ }
+}
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/cmdline.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/cmdline.c Mon Apr 23 12:32:48 2012
@@ -226,7 +226,7 @@ svn_cmdline_init(const char *progname, F
/* Create a pool for use by the UTF-8 routines. It will be cleaned
up by APR at exit time. */
pool = svn_pool_create(NULL);
- svn_utf_initialize(pool);
+ svn_utf_initialize2(pool, FALSE);
if ((err = svn_nls_init()))
{
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/config.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/config.c Mon Apr 23 12:32:48 2012
@@ -34,6 +34,7 @@
#include "config_impl.h"
#include "svn_private_config.h"
+#include "private/svn_dep_compat.h"
@@ -561,6 +562,7 @@ svn_config_get(svn_config_t *cfg, const
const char *section, const char *option,
const char *default_value)
{
+ *valuep = default_value;
if (cfg)
{
cfg_section_t *sec;
@@ -570,23 +572,21 @@ svn_config_get(svn_config_t *cfg, const
make_string_from_option(valuep, cfg, sec, opt, NULL);
}
else
- {
- apr_pool_t *tmp_pool = svn_pool_create(cfg->x_pool);
- const char *x_default;
- expand_option_value(cfg, sec, default_value, &x_default, tmp_pool);
- if (x_default)
- {
- svn_stringbuf_set(cfg->tmp_value, x_default);
- *valuep = cfg->tmp_value->data;
- }
- else
- *valuep = default_value;
- svn_pool_destroy(tmp_pool);
- }
- }
- else
- {
- *valuep = default_value;
+ /* before attempting to expand an option, check for the placeholder.
+ * If none is there, there is no point in calling expand_option_value.
+ */
+ if (default_value && strchr(default_value, '%'))
+ {
+ apr_pool_t *tmp_pool = svn_pool_create(cfg->x_pool);
+ const char *x_default;
+ expand_option_value(cfg, sec, default_value, &x_default, tmp_pool);
+ if (x_default)
+ {
+ svn_stringbuf_set(cfg->tmp_value, x_default);
+ *valuep = cfg->tmp_value->data;
+ }
+ svn_pool_destroy(tmp_pool);
+ }
}
}
@@ -697,6 +697,33 @@ svn_config_set_bool(svn_config_t *cfg,
}
svn_error_t *
+svn_config_get_int64(svn_config_t *cfg,
+ apr_int64_t *valuep,
+ const char *section,
+ const char *option,
+ apr_int64_t default_value)
+{
+ const char *tmp_value;
+ svn_config_get(cfg, &tmp_value, section, option, NULL);
+ if (tmp_value)
+ return svn_cstring_strtoi64(valuep, tmp_value,
+ APR_INT64_MIN, APR_INT64_MAX, 10);
+
+ *valuep = default_value;
+ return SVN_NO_ERROR;
+}
+
+void
+svn_config_set_int64(svn_config_t *cfg,
+ const char *section,
+ const char *option,
+ apr_int64_t value)
+{
+ svn_config_set(cfg, section, option,
+ apr_psprintf(cfg->pool, "%" APR_INT64_T_FMT, value));
+}
+
+svn_error_t *
svn_config_get_yes_no_ask(svn_config_t *cfg, const char **valuep,
const char *section, const char *option,
const char* default_value)
@@ -974,5 +1001,13 @@ svn_config_get_server_setting_bool(svn_c
svn_boolean_t
svn_config_has_section(svn_config_t *cfg, const char *section)
{
- return apr_hash_get(cfg->sections, section, APR_HASH_KEY_STRING) != NULL;
+ cfg_section_t *sec;
+
+ /* Canonicalize the hash key */
+ svn_stringbuf_set(cfg->tmp_key, section);
+ if (! cfg->section_names_case_sensitive)
+ make_hash_key(cfg->tmp_key->data);
+
+ sec = apr_hash_get(cfg->sections, cfg->tmp_key->data, APR_HASH_KEY_STRING);
+ return sec != NULL;
}
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/config_file.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/config_file.c Mon Apr 23 12:32:48 2012
@@ -123,7 +123,7 @@ parser_ungetc(parse_context_t *ctx, int
static APR_INLINE svn_error_t *
skip_whitespace(parse_context_t *ctx, int *c, int *pcount)
{
- int ch;
+ int ch = 0;
int count = 0;
SVN_ERR(parser_getc(ctx, &ch));
@@ -766,16 +766,20 @@ svn_config_ensure(const char *config_dir
"### to authenticate against a" NL
"### Subversion server may be cached" NL
"### to disk in any way." NL
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
"### store-plaintext-passwords Specifies whether passwords may" NL
"### be cached on disk unencrypted." NL
+#endif
"### store-ssl-client-cert-pp Specifies whether passphrase used" NL
"### to authenticate against a client" NL
"### certificate may be cached to disk" NL
"### in any way" NL
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
"### store-ssl-client-cert-pp-plaintext" NL
"### Specifies whether client cert" NL
"### passphrases may be cached on disk" NL
"### unencrypted (i.e., as plaintext)." NL
+#endif
"### store-auth-creds Specifies whether any auth info" NL
"### (passwords as well as server certs)"
NL
@@ -783,15 +787,14 @@ svn_config_ensure(const char *config_dir
"### username Specifies the default username." NL
"###" NL
"### Set store-passwords to 'no' to avoid storing passwords on disk" NL
- "### in any way, including in password stores. It defaults to 'yes',"
- NL
- "### but Subversion will never save your password to disk in plaintext"
- NL
- "### unless you tell it to." NL
+ "### in any way, including in password stores. It defaults to" NL
+ "### 'yes', but Subversion will never save your password to disk in" NL
+ "### plaintext unless explicitly configured to do so." NL
"### Note that this option only prevents saving of *new* passwords;" NL
"### it doesn't invalidate existing passwords. (To do that, remove" NL
"### the cache files by hand as described in the Subversion book.)" NL
"###" NL
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
"### Set store-plaintext-passwords to 'no' to avoid storing" NL
"### passwords in unencrypted form in the auth/ area of your config" NL
"### directory. Set it to 'yes' to allow Subversion to store" NL
@@ -801,11 +804,12 @@ svn_config_ensure(const char *config_dir
"### this option has no effect if either 'store-passwords' or " NL
"### 'store-auth-creds' is set to 'no'." NL
"###" NL
+#endif
"### Set store-ssl-client-cert-pp to 'no' to avoid storing ssl" NL
"### client certificate passphrases in the auth/ area of your" NL
"### config directory. It defaults to 'yes', but Subversion will" NL
- "### never save your passphrase to disk in plaintext unless you tell"NL
- "### it to via 'store-ssl-client-cert-pp-plaintext' (see below)." NL
+ "### never save your passphrase to disk in plaintext unless" NL
+ "### explicitly configured to do so." NL
"###" NL
"### Note store-ssl-client-cert-pp only prevents the saving of *new*"NL
"### passphrases; it doesn't invalidate existing passphrases. To do"NL
@@ -814,6 +818,7 @@ svn_config_ensure(const char *config_dir
"### svn.serverconfig.netmodel.html\\" NL
"### #svn.serverconfig.netmodel.credcache" NL
"###" NL
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
"### Set store-ssl-client-cert-pp-plaintext to 'no' to avoid storing"NL
"### passphrases in unencrypted form in the auth/ area of your" NL
"### config directory. Set it to 'yes' to allow Subversion to" NL
@@ -823,6 +828,7 @@ svn_config_ensure(const char *config_dir
"### this option has no effect if either 'store-auth-creds' or " NL
"### 'store-ssl-client-cert-pp' is set to 'no'." NL
"###" NL
+#endif
"### Set store-auth-creds to 'no' to avoid storing any Subversion" NL
"### credentials in the auth/ area of your config directory." NL
"### Note that this includes SSL server certificates." NL
@@ -858,7 +864,9 @@ svn_config_ensure(const char *config_dir
"# http-auth-types = basic;digest;negotiate" NL
#endif
"# neon-debug-mask = 130" NL
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
"# store-plaintext-passwords = no" NL
+#endif
"# username = harry" NL
"" NL
"### Information for the second group:" NL
@@ -904,9 +912,12 @@ svn_config_ensure(const char *config_dir
"#" NL
"# Password / passphrase caching parameters:" NL
"# store-passwords = no" NL
- "# store-plaintext-passwords = no" NL
"# store-ssl-client-cert-pp = no" NL
- "# store-ssl-client-cert-pp-plaintext = no" NL;
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
+ "# store-plaintext-passwords = no" NL
+ "# store-ssl-client-cert-pp-plaintext = no" NL
+#endif
+ ;
err = svn_io_file_open(&f, path,
(APR_WRITE | APR_CREATE | APR_EXCL),
@@ -1039,7 +1050,7 @@ svn_config_ensure(const char *config_dir
"### path separator. A single backslash will be treated as an" NL
"### escape for the following character." NL
"" NL
- "### Section for configuring miscelleneous Subversion options." NL
+ "### Section for configuring miscellaneous Subversion options." NL
"[miscellany]" NL
"### Set global-ignores to a set of whitespace-delimited globs" NL
"### which Subversion will ignore in its 'status' output, and" NL
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/debug.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/debug.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/debug.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/debug.c Mon Apr 23 12:32:48 2012
@@ -27,10 +27,13 @@
#include <stdarg.h>
#include "svn_types.h"
+#include "svn_string.h"
#include "private/svn_debug.h"
+#define DBG_FLAG "DBG: "
+
/* This will be tweaked by the preamble code. */
static FILE * volatile debug_output = NULL;
@@ -59,21 +62,63 @@ svn_dbg__preamble(const char *file, long
else
++slash;
- fprintf(output, "DBG: %s:%4ld: ", slash, line);
+ fprintf(output, DBG_FLAG "%s:%4ld: ", slash, line);
}
}
-void
-svn_dbg__printf(const char *fmt, ...)
+static void
+print_line(const char *fmt, va_list ap)
{
FILE *output = debug_output;
- va_list ap;
if (output == NULL || quiet_mode())
return;
- va_start(ap, fmt);
(void) vfprintf(output, fmt, ap);
+}
+
+
+void
+svn_dbg__printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ print_line(fmt, ap);
va_end(ap);
}
+
+
+void
+svn_dbg__print_props(apr_hash_t *props,
+ const char *header_fmt,
+ ...)
+{
+/* We only build this code if SVN_DEBUG is defined. */
+#ifdef SVN_DEBUG
+
+ apr_hash_index_t *hi;
+ va_list ap;
+
+ va_start(ap, header_fmt);
+ print_line(header_fmt, ap);
+ va_end(ap);
+
+ if (props == NULL)
+ {
+ SVN_DBG((" (null)\n"));
+ return;
+ }
+
+ for (hi = apr_hash_first(apr_hash_pool_get(props), props); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_string_t *val = svn__apr_hash_index_val(hi);
+
+ SVN_DBG((" '%s' -> '%s'\n", name, val->data));
+ }
+#endif /* SVN_DEBUG */
+}
+
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/deprecated.c Mon Apr 23 12:32:48 2012
@@ -39,6 +39,7 @@
#include "svn_pools.h"
#include "svn_dso.h"
#include "svn_mergeinfo.h"
+#include "svn_utf.h"
#include "svn_xml.h"
#include "opt.h"
@@ -766,6 +767,25 @@ svn_io_get_dirents(apr_hash_t **dirents,
}
svn_error_t *
+svn_io_start_cmd2(apr_proc_t *cmd_proc,
+ const char *path,
+ const char *cmd,
+ const char *const *args,
+ svn_boolean_t inherit,
+ svn_boolean_t infile_pipe,
+ apr_file_t *infile,
+ svn_boolean_t outfile_pipe,
+ apr_file_t *outfile,
+ svn_boolean_t errfile_pipe,
+ apr_file_t *errfile,
+ apr_pool_t *pool)
+{
+ return svn_io_start_cmd3(cmd_proc, path, cmd, args, NULL, inherit,
+ infile_pipe, infile, outfile_pipe, outfile,
+ errfile_pipe, errfile, pool);
+}
+
+svn_error_t *
svn_io_start_cmd(apr_proc_t *cmd_proc,
const char *path,
const char *cmd,
@@ -1173,3 +1193,9 @@ svn_xml_make_header(svn_stringbuf_t **st
{
svn_xml_make_header2(str, NULL, pool);
}
+
+void
+svn_utf_initialize(apr_pool_t *pool)
+{
+ svn_utf_initialize2(pool, FALSE);
+}
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/dirent_uri.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/dirent_uri.c Mon Apr 23 12:32:48 2012
@@ -1295,25 +1295,17 @@ svn_uri_basename(const char *uri, apr_po
{
apr_size_t len = strlen(uri);
apr_size_t start;
- const char *base_name;
assert(svn_uri_is_canonical(uri, NULL));
if (svn_uri_is_root(uri, len))
return "";
- else
- {
- start = len;
- while (start > 0 && uri[start - 1] != '/')
- --start;
- }
- if (pool)
- base_name = apr_pstrmemdup(pool, uri + start, len - start);
- else
- base_name = uri + start;
+ start = len;
+ while (start > 0 && uri[start - 1] != '/')
+ --start;
- return svn_path_uri_decode(base_name, pool);
+ return svn_path_uri_decode(uri + start, pool);
}
void
@@ -2382,10 +2374,10 @@ svn_uri_get_file_url_from_dirent(const c
#else
if (dirent[0] == '/')
{
- /* Handle UNC paths */
- assert(dirent[1] != '/'); /* Not absolute! */
+ /* Handle UNC paths //server/share -> file://server/share */
+ assert(dirent[1] == '/'); /* Expect UNC, not non-absolute */
- *url = apr_pstrcat(pool, "file://", dirent+1, NULL);
+ *url = apr_pstrcat(pool, "file:", dirent, NULL);
}
else
*url = apr_pstrcat(pool, "file:///", dirent, NULL);
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/error.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/error.c Mon Apr 23 12:32:48 2012
@@ -28,6 +28,8 @@
#include <apr_pools.h>
#include <apr_strings.h>
+#include <zlib.h>
+
#include "svn_cmdline.h"
#include "svn_error.h"
#include "svn_pools.h"
@@ -673,3 +675,52 @@ svn_error__malfunction(svn_boolean_t can
{
return malfunction_handler(can_return, file, line, expr);
}
+
+svn_error_t *
+svn_error__wrap_zlib(int zerr, const char *function, const char *message)
+{
+ apr_status_t status;
+ const char *zmsg;
+
+ if (zerr == Z_OK)
+ return SVN_NO_ERROR;
+
+ switch (zerr)
+ {
+ case Z_STREAM_ERROR:
+ status = SVN_ERR_STREAM_MALFORMED_DATA;
+ zmsg = _("stream error");
+ break;
+
+ case Z_MEM_ERROR:
+ status = APR_ENOMEM;
+ zmsg = _("out of memory");
+ break;
+
+ case Z_BUF_ERROR:
+ status = APR_ENOMEM;
+ zmsg = _("buffer error");
+ break;
+
+ case Z_VERSION_ERROR:
+ status = SVN_ERR_STREAM_UNRECOGNIZED_DATA;
+ zmsg = _("version error");
+ break;
+
+ case Z_DATA_ERROR:
+ status = SVN_ERR_STREAM_MALFORMED_DATA;
+ zmsg = _("corrupt data");
+ break;
+
+ default:
+ status = SVN_ERR_STREAM_UNRECOGNIZED_DATA;
+ zmsg = _("unknown error");
+ break;
+ }
+
+ if (message != NULL)
+ return svn_error_createf(status, NULL, "zlib (%s): %s: %s", function,
+ zmsg, message);
+ else
+ return svn_error_createf(status, NULL, "zlib (%s): %s", function, zmsg);
+}
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/gpg_agent.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/gpg_agent.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/gpg_agent.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/gpg_agent.c Mon Apr 23 12:32:48 2012
@@ -154,8 +154,9 @@ send_option(int sd, char *buf, size_t n,
/* Implementation of svn_auth__password_get_t that retrieves the password
from gpg-agent */
-static svn_boolean_t
-password_get_gpg_agent(const char **password,
+static svn_error_t *
+password_get_gpg_agent(svn_boolean_t *done,
+ const char **password,
apr_hash_t *creds,
const char *realmstring,
const char *username,
@@ -168,7 +169,7 @@ password_get_gpg_agent(const char **pass
const char *p = NULL;
char *ep = NULL;
char *buffer;
-
+
apr_array_header_t *socket_details;
const char *request = NULL;
const char *cache_id = NULL;
@@ -182,6 +183,8 @@ password_get_gpg_agent(const char **pass
char *password_prompt;
char *realm_prompt;
+ *done = FALSE;
+
gpg_agent_info = getenv("GPG_AGENT_INFO");
if (gpg_agent_info != NULL)
{
@@ -190,7 +193,7 @@ password_get_gpg_agent(const char **pass
socket_name = APR_ARRAY_IDX(socket_details, 0, const char *);
}
else
- return FALSE;
+ return SVN_NO_ERROR;
if (socket_name != NULL)
{
@@ -200,29 +203,29 @@ password_get_gpg_agent(const char **pass
sd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sd == -1)
- return FALSE;
-
+ return SVN_NO_ERROR;
+
if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
}
else
- return FALSE;
+ return SVN_NO_ERROR;
/* Receive the connection status from the gpg-agent daemon. */
buffer = apr_palloc(pool, BUFFER_SIZE);
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
if (strncmp(buffer, "OK", 2) != 0)
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
/* The GPG-Agent documentation says:
@@ -232,19 +235,19 @@ password_get_gpg_agent(const char **pass
if (write(sd, request, strlen(request)) == -1)
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
if (strncmp(buffer, "D", 1) == 0)
p = &buffer[2];
if (!p)
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
ep = strchr(p, '\n');
if (ep != NULL)
@@ -252,18 +255,18 @@ password_get_gpg_agent(const char **pass
if (strcmp(socket_name, p) != 0)
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
/* The agent will terminate its response with "OK". */
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
if (strncmp(buffer, "OK", 2) != 0)
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
/* Send TTY_NAME to the gpg-agent daemon. */
@@ -273,13 +276,13 @@ password_get_gpg_agent(const char **pass
if (!send_option(sd, buffer, BUFFER_SIZE, "ttyname", tty_name, pool))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
}
else
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
/* Send TTY_TYPE to the gpg-agent daemon. */
@@ -289,13 +292,13 @@ password_get_gpg_agent(const char **pass
if (!send_option(sd, buffer, BUFFER_SIZE, "ttytype", tty_type, pool))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
}
else
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
/* Compute LC_CTYPE. */
@@ -311,7 +314,7 @@ password_get_gpg_agent(const char **pass
if (!send_option(sd, buffer, BUFFER_SIZE, "lc-ctype", lc_ctype, pool))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
}
@@ -323,13 +326,12 @@ password_get_gpg_agent(const char **pass
if (!send_option(sd, buffer, BUFFER_SIZE, "display", display, pool))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
}
/* Create the CACHE_ID which will be generated based on REALMSTRING similar
to other password caching mechanisms. */
- digest = svn_checksum_create(svn_checksum_md5, pool);
svn_checksum(&digest, svn_checksum_md5, realmstring, strlen(realmstring),
pool);
cache_id = svn_checksum_to_cstring(digest, pool);
@@ -348,25 +350,25 @@ password_get_gpg_agent(const char **pass
if (write(sd, request, strlen(request)) == -1)
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
- return FALSE;
+ return SVN_NO_ERROR;
}
close(sd);
if (strncmp(buffer, "ERR", 3) == 0)
- return FALSE;
-
+ return SVN_NO_ERROR;
+
p = NULL;
if (strncmp(buffer, "D", 1) == 0)
p = &buffer[2];
if (!p)
- return FALSE;
+ return SVN_NO_ERROR;
ep = strchr(p, '\n');
if (ep != NULL)
@@ -374,14 +376,20 @@ password_get_gpg_agent(const char **pass
*password = p;
- return TRUE;
+ *done = TRUE;
+ return SVN_NO_ERROR;
}
-/* Implementation of svn_auth__password_set_t that stores the password in
- GPG Agent. */
-static svn_boolean_t
-password_set_gpg_agent(apr_hash_t *creds,
+/* Implementation of svn_auth__password_set_t that would store the
+ password in GPG Agent if that's how this particular integration
+ worked. But it isn't. GPG Agent stores the password provided by
+ the user via the pinentry program immediately upon its provision
+ (and regardless of its accuracy as passwords go), so there's
+ nothing really to do here. */
+static svn_error_t *
+password_set_gpg_agent(svn_boolean_t *done,
+ apr_hash_t *creds,
const char *realmstring,
const char *username,
const char *password,
@@ -389,7 +397,9 @@ password_set_gpg_agent(apr_hash_t *creds
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
- return TRUE;
+ *done = TRUE;
+
+ return SVN_NO_ERROR;
}
@@ -402,12 +412,11 @@ simple_gpg_agent_first_creds(void **cred
const char *realmstring,
apr_pool_t *pool)
{
- return svn_auth__simple_first_creds_helper(credentials,
- iter_baton, provider_baton,
- parameters, realmstring,
- password_get_gpg_agent,
- SVN_AUTH__GPG_AGENT_PASSWORD_TYPE,
- pool);
+ return svn_auth__simple_creds_cache_get(credentials, iter_baton,
+ provider_baton, parameters,
+ realmstring, password_get_gpg_agent,
+ SVN_AUTH__GPG_AGENT_PASSWORD_TYPE,
+ pool);
}
@@ -420,12 +429,11 @@ simple_gpg_agent_save_creds(svn_boolean_
const char *realmstring,
apr_pool_t *pool)
{
- return svn_auth__simple_save_creds_helper(saved, credentials,
- provider_baton, parameters,
- realmstring,
- password_set_gpg_agent,
- SVN_AUTH__GPG_AGENT_PASSWORD_TYPE,
- pool);
+ return svn_auth__simple_creds_cache_set(saved, credentials,
+ provider_baton, parameters,
+ realmstring, password_set_gpg_agent,
+ SVN_AUTH__GPG_AGENT_PASSWORD_TYPE,
+ pool);
}
Propchange: subversion/branches/javahl-ra/subversion/libsvn_subr/gpg_agent.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/io.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/io.c Mon Apr 23 12:32:48 2012
@@ -170,7 +170,7 @@ cstring_from_utf8(const char **path_apr,
/* Set *NAME_P to the UTF-8 representation of directory entry NAME.
- * NAME is in the the internal encoding used by APR; PARENT is in
+ * NAME is in the internal encoding used by APR; PARENT is in
* UTF-8 and in internal (not local) style.
*
* Use PARENT only for generating an error string if the conversion
@@ -438,7 +438,7 @@ svn_io_open_uniquely_named(apr_file_t **
/* The variable parts of unique_name will not require UTF8
conversion. Therefore, if UTF8 conversion had no effect
on it in the first iteration, it won't require conversion
- in any future interation. */
+ in any future iteration. */
needs_utf8_conversion = strcmp(unique_name_apr, unique_name);
}
}
@@ -1343,7 +1343,7 @@ get_default_file_perms(apr_fileperms_t *
static apr_fileperms_t default_perms = 0;
/* Technically, this "racy": Multiple threads may use enter here and
- try to figure out the default permisission concurrently. That's fine
+ try to figure out the default permission concurrently. That's fine
since they will end up with the same results. Even more technical,
apr_fileperms_t is an atomic type on 32+ bit machines.
*/
@@ -1555,7 +1555,7 @@ static apr_status_t io_utf8_to_unicode_p
* Allocate the maximum string length based on leading 4
* characters of \\?\ (allowing nearly unlimited path lengths)
* plus the trailing null, then transform /'s into \\'s since
- * the \\?\ form doesn't allow '/' path seperators.
+ * the \\?\ form doesn't allow '/' path separators.
*
* Note that the \\?\ form only works for local drive paths, and
* \\?\UNC\ is needed UNC paths.
@@ -1565,7 +1565,7 @@ static apr_status_t io_utf8_to_unicode_p
apr_status_t rv;
/* This is correct, we don't twist the filename if it will
- * definately be shorter than 248 characters. It merits some
+ * definitely be shorter than 248 characters. It merits some
* performance testing to see if this has any effect, but there
* seem to be applications that get confused by the resulting
* Unicode \\?\ style file names, especially if they use argv[0]
@@ -1866,29 +1866,25 @@ file_clear_locks(void *arg)
#endif
svn_error_t *
-svn_io_file_lock2(const char *lock_file,
- svn_boolean_t exclusive,
- svn_boolean_t nonblocking,
- apr_pool_t *pool)
+svn_io_lock_open_file(apr_file_t *lockfile_handle,
+ svn_boolean_t exclusive,
+ svn_boolean_t nonblocking,
+ apr_pool_t *pool)
{
int locktype = APR_FLOCK_SHARED;
- apr_file_t *lockfile_handle;
- apr_int32_t flags;
apr_status_t apr_err;
+ const char *fname;
if (exclusive)
locktype = APR_FLOCK_EXCLUSIVE;
-
- flags = APR_READ;
- if (locktype == APR_FLOCK_EXCLUSIVE)
- flags |= APR_WRITE;
-
if (nonblocking)
locktype |= APR_FLOCK_NONBLOCK;
- SVN_ERR(svn_io_file_open(&lockfile_handle, lock_file, flags,
- APR_OS_DEFAULT,
- pool));
+ /* We need this only in case of an error but this is cheap to get -
+ * so we do it here for clarity. */
+ apr_err = apr_file_name_get(&fname, lockfile_handle);
+ if (apr_err)
+ return svn_error_wrap_apr(apr_err, _("Can't get file name"));
/* Get lock on the filehandle. */
apr_err = apr_file_lock(lockfile_handle, locktype);
@@ -1915,11 +1911,11 @@ svn_io_file_lock2(const char *lock_file,
case APR_FLOCK_SHARED:
return svn_error_wrap_apr(apr_err,
_("Can't get shared lock on file '%s'"),
- svn_dirent_local_style(lock_file, pool));
+ fname);
case APR_FLOCK_EXCLUSIVE:
return svn_error_wrap_apr(apr_err,
_("Can't get exclusive lock on file '%s'"),
- svn_dirent_local_style(lock_file, pool));
+ fname);
default:
SVN_ERR_MALFUNCTION();
}
@@ -1936,6 +1932,61 @@ svn_io_file_lock2(const char *lock_file,
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_io_unlock_open_file(apr_file_t *lockfile_handle,
+ apr_pool_t *pool)
+{
+ const char *fname;
+ apr_status_t apr_err;
+
+ /* We need this only in case of an error but this is cheap to get -
+ * so we do it here for clarity. */
+ apr_err = apr_file_name_get(&fname, lockfile_handle);
+ if (apr_err)
+ return svn_error_wrap_apr(apr_err, _("Can't get file name"));
+
+ /* The actual unlock attempt. */
+ apr_err = apr_file_unlock(lockfile_handle);
+ if (apr_err)
+ return svn_error_wrap_apr(apr_err, _("Can't unlock file '%s'"), fname);
+
+/* On Windows and OS/2 file locks are automatically released when
+ the file handle closes */
+#if !defined(WIN32) && !defined(__OS2__)
+ apr_pool_cleanup_kill(pool, lockfile_handle, file_clear_locks);
+#endif
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_io_file_lock2(const char *lock_file,
+ svn_boolean_t exclusive,
+ svn_boolean_t nonblocking,
+ apr_pool_t *pool)
+{
+ int locktype = APR_FLOCK_SHARED;
+ apr_file_t *lockfile_handle;
+ apr_int32_t flags;
+
+ if (exclusive)
+ locktype = APR_FLOCK_EXCLUSIVE;
+
+ flags = APR_READ;
+ if (locktype == APR_FLOCK_EXCLUSIVE)
+ flags |= APR_WRITE;
+
+ if (nonblocking)
+ locktype |= APR_FLOCK_NONBLOCK;
+
+ SVN_ERR(svn_io_file_open(&lockfile_handle, lock_file, flags,
+ APR_OS_DEFAULT,
+ pool));
+
+ /* Get lock on the filehandle. */
+ return svn_io_lock_open_file(lockfile_handle, exclusive, nonblocking, pool);
+}
+
/* Data consistency/coherency operations. */
@@ -2173,7 +2224,7 @@ svn_io_remove_dir(const char *path, apr_
}
/*
- Mac OS X has a bug where if you're readding the contents of a
+ Mac OS X has a bug where if you're reading the contents of a
directory via readdir in a loop, and you remove one of the entries in
the directory and the directory has 338 or more files in it you will
skip over some of the entries in the directory. Needless to say,
@@ -2417,10 +2468,11 @@ handle_child_process_error(apr_pool_t *p
svn_error_t *
-svn_io_start_cmd2(apr_proc_t *cmd_proc,
+svn_io_start_cmd3(apr_proc_t *cmd_proc,
const char *path,
const char *cmd,
const char *const *args,
+ const char *const *env,
svn_boolean_t inherit,
svn_boolean_t infile_pipe,
apr_file_t *infile,
@@ -2542,8 +2594,8 @@ svn_io_start_cmd2(apr_proc_t *cmd_proc,
/* Start the cmd command. */
- apr_err = apr_proc_create(cmd_proc, cmd_apr, args_native, NULL,
- cmdproc_attr, pool);
+ apr_err = apr_proc_create(cmd_proc, cmd_apr, args_native,
+ inherit ? NULL : env, cmdproc_attr, pool);
if (apr_err)
return svn_error_wrap_apr(apr_err, _("Can't start process '%s'"), cmd);
@@ -2980,6 +3032,13 @@ svn_io_is_binary_data(const void *data,
{
const unsigned char *buf = data;
+ if (len == 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
+ {
+ /* This is an empty UTF-8 file which only contains the UTF-8 BOM.
+ * Treat it as plain text. */
+ return FALSE;
+ }
+
/* Right now, this function is going to be really stupid. It's
going to examine the block of data, and make sure that 15%
of the bytes are such that their value is in the ranges 0x07-0x0D
@@ -3272,6 +3331,15 @@ svn_io_write_unique(const char **tmp_pat
svn_error_t *
svn_io_file_trunc(apr_file_t *file, apr_off_t offset, apr_pool_t *pool)
{
+ /* This is a work-around. APR would flush the write buffer
+ _after_ truncating the file causing now invalid buffered
+ data to be written behind OFFSET. */
+ SVN_ERR(do_io_file_wrapper_cleanup
+ (file, apr_file_flush(file),
+ N_("Can't flush file '%s'"),
+ N_("Can't flush stream"),
+ pool));
+
return do_io_file_wrapper_cleanup
(file, apr_file_trunc(file, offset),
N_("Can't truncate file '%s'"),