Modified: subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_delta/svndiff.c Sun Jun 14 20:58:10 2015 @@ -36,6 +36,20 @@ #include "private/svn_string_private.h" #include "private/svn_dep_compat.h" +static const char SVNDIFF_V0[] = { 'S', 'V', 'N', 0 }; +static const char SVNDIFF_V1[] = { 'S', 'V', 'N', 1 }; + +#define SVNDIFF_HEADER_SIZE (sizeof(SVNDIFF_V0)) + +static const char * +get_svndiff_header(int version) +{ + if (version == 1) + return SVNDIFF_V1; + else + return SVNDIFF_V0; +} + /* ----- Text delta to svndiff ----- */ /* We make one of these and get it passed back to us in calls to the @@ -46,7 +60,8 @@ struct encoder_baton { svn_boolean_t header_done; int version; int compression_level; - apr_pool_t *pool; + /* Pool for temporary allocations, will be cleared periodically. */ + apr_pool_t *scratch_pool; }; /* This is at least as big as the largest size for a single instruction. */ @@ -72,7 +87,7 @@ static svn_error_t * send_simple_insertion_window(svn_txdelta_window_t *window, struct encoder_baton *eb) { - unsigned char headers[4 + 5 * SVN__MAX_ENCODED_UINT_LEN + unsigned char headers[SVNDIFF_HEADER_SIZE + 5 * SVN__MAX_ENCODED_UINT_LEN + MAX_INSTRUCTION_LEN]; unsigned char ibuf[MAX_INSTRUCTION_LEN]; unsigned char *header_current; @@ -89,11 +104,8 @@ send_simple_insertion_window(svn_txdelta if (!eb->header_done) { eb->header_done = TRUE; - headers[0] = 'S'; - headers[1] = 'V'; - headers[2] = 'N'; - headers[3] = (unsigned char)eb->version; - header_current = headers + 4; + memcpy(headers, get_svndiff_header(eb->version), SVNDIFF_HEADER_SIZE); + header_current = headers + SVNDIFF_HEADER_SIZE; } else { @@ -135,58 +147,28 @@ send_simple_insertion_window(svn_txdelta return SVN_NO_ERROR; } +/* Encodes delta window WINDOW to svndiff-format. + The svndiff version is VERSION. COMPRESSION_LEVEL is the zlib + compression level to use. + Returned values will be allocated in POOL or refer to *WINDOW + fields. */ static svn_error_t * -window_handler(svn_txdelta_window_t *window, void *baton) +encode_window(svn_stringbuf_t **instructions_p, + svn_stringbuf_t **header_p, + const svn_string_t **newdata_p, + svn_txdelta_window_t *window, + int version, + int compression_level, + apr_pool_t *pool) { - struct encoder_baton *eb = baton; - apr_pool_t *pool; svn_stringbuf_t *instructions; - svn_stringbuf_t *i1; svn_stringbuf_t *header; const svn_string_t *newdata; unsigned char ibuf[MAX_INSTRUCTION_LEN], *ip; const svn_txdelta_op_t *op; - apr_size_t len; - - /* use specialized code if there is no source */ - if (window && !window->src_ops && window->num_ops == 1 && !eb->version) - return svn_error_trace(send_simple_insertion_window(window, eb)); - - /* Make sure we write the header. */ - if (!eb->header_done) - { - char svnver[4] = {'S','V','N','\0'}; - len = 4; - svnver[3] = (char)eb->version; - SVN_ERR(svn_stream_write(eb->output, svnver, &len)); - eb->header_done = TRUE; - } - - if (window == NULL) - { - svn_stream_t *output = eb->output; - - /* We're done; clean up. - - We clean our pool first. Given that the output stream was passed - TO us, we'll assume it has a longer lifetime, and that it will not - be affected by our pool destruction. - - The contrary point of view (close the stream first): that could - tell our user that everything related to the output stream is done, - and a cleanup of the user pool should occur. However, that user - pool could include the subpool we created for our work (eb->pool), - which would then make our call to svn_pool_destroy() puke. - */ - svn_pool_destroy(eb->pool); - - return svn_stream_close(output); - } /* create the necessary data buffers */ - pool = svn_pool_create(eb->pool); instructions = svn_stringbuf_create_empty(pool); - i1 = svn_stringbuf_create_empty(pool); header = svn_stringbuf_create_empty(pool); /* Encode the instructions. */ @@ -213,21 +195,21 @@ window_handler(svn_txdelta_window_t *win append_encoded_int(header, window->sview_offset); append_encoded_int(header, window->sview_len); append_encoded_int(header, window->tview_len); - if (eb->version == 1) + if (version == 1) { - SVN_ERR(svn__compress(instructions, i1, eb->compression_level)); - instructions = i1; + svn_stringbuf_t *compressed_instructions; + compressed_instructions = svn_stringbuf_create_empty(pool); + SVN_ERR(svn__compress(instructions->data, instructions->len, + compressed_instructions, compression_level)); + instructions = compressed_instructions; } append_encoded_int(header, instructions->len); - if (eb->version == 1) + if (version == 1) { svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool); - svn_stringbuf_t *original = svn_stringbuf_create_empty(pool); - original->data = (char *)window->new_data->data; /* won't be modified */ - original->len = window->new_data->len; - original->blocksize = window->new_data->len + 1; - SVN_ERR(svn__compress(original, compressed, eb->compression_level)); + SVN_ERR(svn__compress(window->new_data->data, window->new_data->len, + compressed, compression_level)); newdata = svn_stringbuf__morph_into_string(compressed); } else @@ -235,6 +217,51 @@ window_handler(svn_txdelta_window_t *win append_encoded_int(header, newdata->len); + *instructions_p = instructions; + *header_p = header; + *newdata_p = newdata; + + return SVN_NO_ERROR; +} + +static svn_error_t * +window_handler(svn_txdelta_window_t *window, void *baton) +{ + struct encoder_baton *eb = baton; + apr_size_t len; + svn_stringbuf_t *instructions; + svn_stringbuf_t *header; + const svn_string_t *newdata; + + /* use specialized code if there is no source */ + if (window && !window->src_ops && window->num_ops == 1 && !eb->version) + return svn_error_trace(send_simple_insertion_window(window, eb)); + + /* Make sure we write the header. */ + if (!eb->header_done) + { + len = SVNDIFF_HEADER_SIZE; + SVN_ERR(svn_stream_write(eb->output, get_svndiff_header(eb->version), + &len)); + eb->header_done = TRUE; + } + + if (window == NULL) + { + /* We're done; clean up. */ + SVN_ERR(svn_stream_close(eb->output)); + + svn_pool_destroy(eb->scratch_pool); + + return SVN_NO_ERROR; + } + + svn_pool_clear(eb->scratch_pool); + + SVN_ERR(encode_window(&instructions, &header, &newdata, window, + eb->version, eb->compression_level, + eb->scratch_pool)); + /* Write out the window. */ len = header->len; SVN_ERR(svn_stream_write(eb->output, header->data, &len)); @@ -249,7 +276,6 @@ window_handler(svn_txdelta_window_t *win SVN_ERR(svn_stream_write(eb->output, newdata->data, &len)); } - svn_pool_destroy(pool); return SVN_NO_ERROR; } @@ -261,13 +287,12 @@ svn_txdelta_to_svndiff3(svn_txdelta_wind int compression_level, apr_pool_t *pool) { - apr_pool_t *subpool = svn_pool_create(pool); struct encoder_baton *eb; - eb = apr_palloc(subpool, sizeof(*eb)); + eb = apr_palloc(pool, sizeof(*eb)); eb->output = output; eb->header_done = FALSE; - eb->pool = subpool; + eb->scratch_pool = svn_pool_create(pool); eb->version = svndiff_version; eb->compression_level = compression_level; @@ -334,6 +359,17 @@ struct decode_baton /* svndiff version in use by delta. */ unsigned char version; + + /* Length of parsed delta window header. 0 if window is not parsed yet. */ + apr_size_t window_header_len; + + /* Five integer fields of parsed delta window header. Valid only if + WINDOW_HEADER_LEN > 0 */ + svn_filesize_t sview_offset; + apr_size_t sview_len; + apr_size_t tview_len; + apr_size_t inslen; + apr_size_t newlen; }; @@ -360,7 +396,7 @@ decode_size(apr_size_t *val, const unsigned char *result = svn__decode_uint(&temp, p, end); if (temp > APR_SIZE_MAX) return NULL; - + *val = (apr_size_t)temp; return result; } @@ -483,21 +519,6 @@ count_and_verify_instructions(int *ninst return SVN_NO_ERROR; } -static svn_error_t * -zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out, - apr_size_t limit) -{ - /* construct a fake string buffer as parameter to svn__decompress. - This is fine as that function never writes to it. */ - svn_stringbuf_t compressed; - compressed.pool = NULL; - compressed.data = (char *)in; - compressed.len = inLen; - compressed.blocksize = inLen + 1; - - return svn__decompress(&compressed, out, limit); -} - /* Given the five integer fields of a window header and a pointer to the remainder of the window contents, fill in a delta window structure *WINDOW. New allocations will be performed in POOL; @@ -513,7 +534,7 @@ decode_window(svn_txdelta_window_t *wind int ninst; apr_size_t npos; svn_txdelta_op_t *ops, *op; - svn_string_t *new_data = apr_palloc(pool, sizeof(*new_data)); + svn_string_t *new_data; window->sview_offset = sview_offset; window->sview_len = sview_len; @@ -526,28 +547,22 @@ decode_window(svn_txdelta_window_t *wind svn_stringbuf_t *instout = svn_stringbuf_create_empty(pool); svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool); - SVN_ERR(zlib_decode(insend, newlen, ndout, - SVN_DELTA_WINDOW_SIZE)); - SVN_ERR(zlib_decode(data, insend - data, instout, - MAX_INSTRUCTION_SECTION_LEN)); + SVN_ERR(svn__decompress(insend, newlen, ndout, + SVN_DELTA_WINDOW_SIZE)); + SVN_ERR(svn__decompress(data, insend - data, instout, + MAX_INSTRUCTION_SECTION_LEN)); newlen = ndout->len; data = (unsigned char *)instout->data; insend = (unsigned char *)instout->data + instout->len; - new_data->data = (const char *) ndout->data; - new_data->len = newlen; + new_data = svn_stringbuf__morph_into_string(ndout); } else { /* Copy the data because an svn_string_t must have the invariant data[len]=='\0'. */ - char *buf = apr_palloc(pool, newlen + 1); - - memcpy(buf, insend, newlen); - buf[newlen] = '\0'; - new_data->data = buf; - new_data->len = newlen; + new_data = svn_string_ncreate((const char*)insend, newlen, pool); } /* Count the instructions and make sure they are all valid. */ @@ -578,10 +593,6 @@ decode_window(svn_txdelta_window_t *wind return SVN_NO_ERROR; } -static const char SVNDIFF_V0[] = { 'S', 'V', 'N', 0 }; -static const char SVNDIFF_V1[] = { 'S', 'V', 'N', 1 }; -#define SVNDIFF_HEADER_SIZE (sizeof(SVNDIFF_V0)) - static svn_error_t * write_handler(void *baton, const char *buffer, @@ -589,8 +600,6 @@ write_handler(void *baton, { struct decode_baton *db = (struct decode_baton *) baton; const unsigned char *p, *end; - svn_filesize_t sview_offset; - apr_size_t sview_len, tview_len, inslen, newlen, remaining; apr_size_t buflen = *len; /* Chew up four bytes at the beginning for the header. */ @@ -628,90 +637,114 @@ write_handler(void *baton, while (1) { - apr_pool_t *newpool; svn_txdelta_window_t window; /* Read the header, if we have enough bytes for that. */ p = (const unsigned char *) db->buffer->data; end = (const unsigned char *) db->buffer->data + db->buffer->len; - p = decode_file_offset(&sview_offset, p, end); - if (p == NULL) - return SVN_NO_ERROR; - - p = decode_size(&sview_len, p, end); - if (p == NULL) - return SVN_NO_ERROR; - - p = decode_size(&tview_len, p, end); - if (p == NULL) - return SVN_NO_ERROR; - - p = decode_size(&inslen, p, end); - if (p == NULL) - return SVN_NO_ERROR; - - p = decode_size(&newlen, p, end); - if (p == NULL) - return SVN_NO_ERROR; - - if (tview_len > SVN_DELTA_WINDOW_SIZE || - sview_len > SVN_DELTA_WINDOW_SIZE || - /* for svndiff1, newlen includes the original length */ - newlen > SVN_DELTA_WINDOW_SIZE + SVN__MAX_ENCODED_UINT_LEN || - inslen > MAX_INSTRUCTION_SECTION_LEN) - return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, - _("Svndiff contains a too-large window")); - - /* Check for integer overflow. */ - if (sview_offset < 0 || inslen + newlen < inslen - || sview_len + tview_len < sview_len - || (apr_size_t)sview_offset + sview_len < (apr_size_t)sview_offset) - return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, - _("Svndiff contains corrupt window header")); - - /* Check for source windows which slide backwards. */ - if (sview_len > 0 - && (sview_offset < db->last_sview_offset + if (db->window_header_len == 0) + { + svn_filesize_t sview_offset; + apr_size_t sview_len, tview_len, inslen, newlen; + const unsigned char *hdr_start = p; + + p = decode_file_offset(&sview_offset, p, end); + if (p == NULL) + break; + + p = decode_size(&sview_len, p, end); + if (p == NULL) + break; + + p = decode_size(&tview_len, p, end); + if (p == NULL) + break; + + p = decode_size(&inslen, p, end); + if (p == NULL) + break; + + p = decode_size(&newlen, p, end); + if (p == NULL) + break; + + if (tview_len > SVN_DELTA_WINDOW_SIZE || + sview_len > SVN_DELTA_WINDOW_SIZE || + /* for svndiff1, newlen includes the original length */ + newlen > SVN_DELTA_WINDOW_SIZE + SVN__MAX_ENCODED_UINT_LEN || + inslen > MAX_INSTRUCTION_SECTION_LEN) + return svn_error_create( + SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, + _("Svndiff contains a too-large window")); + + /* Check for integer overflow. */ + if (sview_offset < 0 || inslen + newlen < inslen + || sview_len + tview_len < sview_len + || (apr_size_t)sview_offset + sview_len < (apr_size_t)sview_offset) + return svn_error_create( + SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, + _("Svndiff contains corrupt window header")); + + /* Check for source windows which slide backwards. */ + if (sview_len > 0 + && (sview_offset < db->last_sview_offset || (sview_offset + sview_len < db->last_sview_offset + db->last_sview_len))) - return svn_error_create - (SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL, - _("Svndiff has backwards-sliding source views")); + return svn_error_create( + SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL, + _("Svndiff has backwards-sliding source views")); + + /* Remember parsed window header. */ + db->window_header_len = p - hdr_start; + db->sview_offset = sview_offset; + db->sview_len = sview_len; + db->tview_len = tview_len; + db->inslen = inslen; + db->newlen = newlen; + } + else + { + /* Skip already parsed window header. */ + p += db->window_header_len; + } /* Wait for more data if we don't have enough bytes for the whole window. */ - if ((apr_size_t) (end - p) < inslen + newlen) + if ((apr_size_t) (end - p) < db->inslen + db->newlen) return SVN_NO_ERROR; /* Decode the window and send it off. */ - SVN_ERR(decode_window(&window, sview_offset, sview_len, tview_len, - inslen, newlen, p, db->subpool, - db->version)); + SVN_ERR(decode_window(&window, db->sview_offset, db->sview_len, + db->tview_len, db->inslen, db->newlen, p, + db->subpool, db->version)); SVN_ERR(db->consumer_func(&window, db->consumer_baton)); - /* Make a new subpool and buffer, saving aside the remaining - data in the old buffer. */ - newpool = svn_pool_create(db->pool); - p += inslen + newlen; - remaining = db->buffer->data + db->buffer->len - (const char *) p; - db->buffer = - svn_stringbuf_ncreate((const char *) p, remaining, newpool); + p += db->inslen + db->newlen; + + /* Remove processed data from the buffer. */ + svn_stringbuf_remove(db->buffer, 0, db->buffer->len - (end - p)); + + /* Reset window header length. */ + db->window_header_len = 0; /* Remember the offset and length of the source view for next time. */ - db->last_sview_offset = sview_offset; - db->last_sview_len = sview_len; + db->last_sview_offset = db->sview_offset; + db->last_sview_len = db->sview_len; - /* We've copied stuff out of the old pool. Toss that pool and use - our new pool. - ### might be nice to avoid the copy and just use svn_pool_clear - ### to get rid of whatever the "other stuff" is. future project... - */ - svn_pool_destroy(db->subpool); - db->subpool = newpool; + /* Clear subpool. */ + svn_pool_clear(db->subpool); } - /* NOTREACHED */ + /* At this point we processed all integral windows and DB->BUFFER is empty + or contains partially read window header. + Check that unprocessed data is not larger than theoretical maximum + window header size. */ + if (db->buffer->len > 5 * SVN__MAX_ENCODED_UINT_LEN) + return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, + _("Svndiff contains a too-large window header")); + + return SVN_NO_ERROR; } /* Minimal svn_stream_t write handler, doing nothing */ @@ -749,23 +782,25 @@ svn_txdelta_parse_svndiff(svn_txdelta_wi svn_boolean_t error_on_early_close, apr_pool_t *pool) { - apr_pool_t *subpool = svn_pool_create(pool); - struct decode_baton *db = apr_palloc(pool, sizeof(*db)); svn_stream_t *stream; - db->consumer_func = handler; - db->consumer_baton = handler_baton; - db->pool = subpool; - db->subpool = svn_pool_create(subpool); - db->buffer = svn_stringbuf_create_empty(db->subpool); - db->last_sview_offset = 0; - db->last_sview_len = 0; - db->header_bytes = 0; - db->error_on_early_close = error_on_early_close; - stream = svn_stream_create(db, pool); - if (handler != svn_delta_noop_window_handler) { + apr_pool_t *subpool = svn_pool_create(pool); + struct decode_baton *db = apr_palloc(pool, sizeof(*db)); + + db->consumer_func = handler; + db->consumer_baton = handler_baton; + db->pool = subpool; + db->subpool = svn_pool_create(subpool); + db->buffer = svn_stringbuf_create_empty(db->pool); + db->last_sview_offset = 0; + db->last_sview_len = 0; + db->header_bytes = 0; + db->error_on_early_close = error_on_early_close; + db->window_header_len = 0; + stream = svn_stream_create(db, pool); + svn_stream_set_write(stream, write_handler); svn_stream_set_close(stream, close_handler); } @@ -773,6 +808,7 @@ svn_txdelta_parse_svndiff(svn_txdelta_wi { /* And else we just ignore everything as efficiently as we can. by only hooking a no-op handler */ + stream = svn_stream_create(NULL, pool); svn_stream_set_write(stream, noop_write_handler); } return stream; @@ -796,7 +832,7 @@ read_one_byte(unsigned char *byte, svn_s return SVN_NO_ERROR; } -/* Read and decode one integer from STREAM into *SIZE. +/* Read and decode one integer from STREAM into *SIZE. Increment *BYTE_COUNTER by the number of chars we have read. */ static svn_error_t * read_one_size(apr_size_t *size,
Modified: subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_delta/text_delta.c Sun Jun 14 20:58:10 2015 @@ -180,8 +180,7 @@ svn_txdelta_window_dup(const svn_txdelta build_baton.num_ops = window->num_ops; build_baton.src_ops = window->src_ops; build_baton.ops_size = window->num_ops; - build_baton.ops = apr_palloc(pool, ops_size); - memcpy(build_baton.ops, window->ops, ops_size); + build_baton.ops = apr_pmemdup(pool, window->ops, ops_size); build_baton.new_data = svn_stringbuf_create_from_string(window->new_data, pool); Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_diff/binary_diff.c Sun Jun 14 20:58:10 2015 @@ -42,7 +42,6 @@ create_compressed(apr_file_t **result, { svn_stream_t *compressed; svn_filesize_t bytes_read = 0; - apr_finfo_t finfo; apr_size_t rd; SVN_ERR(svn_io_open_uniquely_named(result, NULL, NULL, "diffgz", @@ -56,7 +55,7 @@ create_compressed(apr_file_t **result, if (original_stream) do { - char buffer[SVN_STREAM_CHUNK_SIZE]; + char buffer[SVN__STREAM_CHUNK_SIZE]; rd = sizeof(buffer); if (cancel_func) @@ -67,7 +66,7 @@ create_compressed(apr_file_t **result, bytes_read += rd; SVN_ERR(svn_stream_write(compressed, buffer, &rd)); } - while(rd == SVN_STREAM_CHUNK_SIZE); + while(rd == SVN__STREAM_CHUNK_SIZE); else { apr_size_t zero = 0; @@ -77,8 +76,7 @@ create_compressed(apr_file_t **result, SVN_ERR(svn_stream_close(compressed)); /* Flush compression */ *full_size = bytes_read; - SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, *result, scratch_pool)); - *compressed_size = finfo.size; + SVN_ERR(svn_io_file_size_get(compressed_size, *result, scratch_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_file.c Sun Jun 14 20:58:10 2015 @@ -777,7 +777,6 @@ datasources_open(void *baton, { svn_diff__file_baton_t *file_baton = baton; struct file_info files[4]; - apr_finfo_t finfo[4]; apr_off_t length[4]; #ifndef SVN_DISABLE_PREFIX_SUFFIX_SCANNING svn_boolean_t reached_one_eof; @@ -792,14 +791,14 @@ datasources_open(void *baton, /* Open datasources and read first chunk */ for (i = 0; i < datasources_len; i++) { + svn_filesize_t filesize; struct file_info *file = &file_baton->files[datasource_to_index(datasources[i])]; SVN_ERR(svn_io_file_open(&file->file, file->path, APR_READ, APR_OS_DEFAULT, file_baton->pool)); - SVN_ERR(svn_io_file_info_get(&finfo[i], APR_FINFO_SIZE, - file->file, file_baton->pool)); - file->size = finfo[i].size; - length[i] = finfo[i].size > CHUNK_SIZE ? CHUNK_SIZE : finfo[i].size; + SVN_ERR(svn_io_file_size_get(&filesize, file->file, file_baton->pool)); + file->size = filesize; + length[i] = filesize > CHUNK_SIZE ? CHUNK_SIZE : filesize; file->buffer = apr_palloc(file_baton->pool, (apr_size_t) length[i]); SVN_ERR(read_chunk(file->file, file->buffer, length[i], 0, file_baton->pool)); @@ -1956,7 +1955,7 @@ typedef struct context_saver_t { const char **data; /* const char *data[context_size] */ apr_size_t *len; /* apr_size_t len[context_size] */ apr_size_t next_slot; - apr_size_t total_written; + apr_ssize_t total_writes; } context_saver_t; @@ -1972,7 +1971,7 @@ context_saver_stream_write(void *baton, cs->data[cs->next_slot] = data; cs->len[cs->next_slot] = *len; cs->next_slot = (cs->next_slot + 1) % cs->context_size; - cs->total_written++; + cs->total_writes++; } return SVN_NO_ERROR; } @@ -2252,7 +2251,7 @@ output_conflict_with_context(svn_diff3__ trailing context)? If so, flush it. */ if (btn->output_stream == btn->context_saver->stream) { - if (btn->context_saver->total_written > btn->context_size) + if (btn->context_saver->total_writes > btn->context_size) SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n")); SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream)); } @@ -2360,7 +2359,7 @@ svn_diff_file_output_merge3(svn_stream_t svn_diff_conflict_display_style_t style, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_diff3__file_output_baton_t baton; apr_file_t *file[3]; @@ -2376,7 +2375,7 @@ svn_diff_file_output_merge3(svn_stream_t baton.context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE; if (conflicts_only) { - baton.pool = svn_pool_create(pool); + baton.pool = svn_pool_create(scratch_pool); make_context_saver(&baton); baton.real_output_stream = output_stream; } @@ -2387,22 +2386,22 @@ svn_diff_file_output_merge3(svn_stream_t baton.path[2] = latest_path; SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_modified, conflict_modified ? conflict_modified - : apr_psprintf(pool, "<<<<<<< %s", + : apr_psprintf(scratch_pool, "<<<<<<< %s", modified_path), - pool)); + scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_original, conflict_original ? conflict_original - : apr_psprintf(pool, "||||||| %s", + : apr_psprintf(scratch_pool, "||||||| %s", original_path), - pool)); + scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_separator, conflict_separator ? conflict_separator - : "=======", pool)); + : "=======", scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_latest, conflict_latest ? conflict_latest - : apr_psprintf(pool, ">>>>>>> %s", + : apr_psprintf(scratch_pool, ">>>>>>> %s", latest_path), - pool)); + scratch_pool)); baton.conflict_style = style; @@ -2413,7 +2412,7 @@ svn_diff_file_output_merge3(svn_stream_t SVN_ERR(map_or_read_file(&file[idx], MMAP_T_ARG(mm[idx]) &baton.buffer[idx], &size, - baton.path[idx], pool)); + baton.path[idx], scratch_pool)); baton.curp[idx] = baton.buffer[idx]; baton.endp[idx] = baton.buffer[idx]; @@ -2454,7 +2453,7 @@ svn_diff_file_output_merge3(svn_stream_t if (file[idx]) { - SVN_ERR(svn_io_file_close(file[idx], pool)); + SVN_ERR(svn_io_file_close(file[idx], scratch_pool)); } } Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_diff/diff_memory.c Sun Jun 14 20:58:10 2015 @@ -622,7 +622,7 @@ svn_diff_mem_string_output_unified3(svn_ int context_size, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { if (svn_diff_contains_diffs(diff)) @@ -631,9 +631,9 @@ svn_diff_mem_string_output_unified3(svn_ memset(&baton, 0, sizeof(baton)); baton.output_stream = output_stream; - baton.pool = svn_pool_create(pool); + baton.pool = svn_pool_create(scratch_pool); baton.header_encoding = header_encoding; - baton.hunk = svn_stringbuf_create_empty(pool); + baton.hunk = svn_stringbuf_create_empty(scratch_pool); baton.hunk_delimiter = hunk_delimiter; baton.no_newline_string = (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0) @@ -644,22 +644,22 @@ svn_diff_mem_string_output_unified3(svn_ SVN_ERR(svn_utf_cstring_from_utf8_ex2 (&(baton.prefix_str[unified_output_context]), " ", - header_encoding, pool)); + header_encoding, scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8_ex2 (&(baton.prefix_str[unified_output_delete]), "-", - header_encoding, pool)); + header_encoding, scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8_ex2 (&(baton.prefix_str[unified_output_insert]), "+", - header_encoding, pool)); + header_encoding, scratch_pool)); - fill_source_tokens(&baton.sources[0], original, pool); - fill_source_tokens(&baton.sources[1], modified, pool); + fill_source_tokens(&baton.sources[0], original, scratch_pool); + fill_source_tokens(&baton.sources[1], modified, scratch_pool); if (with_diff_header) { SVN_ERR(svn_diff__unidiff_write_header( output_stream, header_encoding, - original_header, modified_header, pool)); + original_header, modified_header, scratch_pool)); } SVN_ERR(svn_diff_output2(diff, &baton, @@ -688,7 +688,7 @@ typedef struct context_saver_t { const char **data; /* const char *data[context_size] */ apr_size_t *len; /* apr_size_t len[context_size] */ apr_size_t next_slot; - apr_size_t total_written; + apr_ssize_t total_writes; } context_saver_t; @@ -701,7 +701,7 @@ context_saver_stream_write(void *baton, cs->data[cs->next_slot] = data; cs->len[cs->next_slot] = *len; cs->next_slot = (cs->next_slot + 1) % cs->context_size; - cs->total_written++; + cs->total_writes++; return SVN_NO_ERROR; } @@ -822,13 +822,11 @@ make_trailing_context_printer(merge_outp static svn_error_t * -output_merge_token_range(apr_size_t *lines_printed_p, - merge_output_baton_t *btn, +output_merge_token_range(merge_output_baton_t *btn, int idx, apr_off_t first, apr_off_t length) { apr_array_header_t *tokens = btn->sources[idx].tokens; - apr_size_t lines_printed = 0; for (; length > 0 && first < tokens->nelts; length--, first++) { @@ -838,12 +836,8 @@ output_merge_token_range(apr_size_t *lin /* Note that the trailing context printer assumes that svn_stream_write is called exactly once per line. */ SVN_ERR(svn_stream_write(btn->output_stream, token->data, &len)); - lines_printed++; } - if (lines_printed_p) - *lines_printed_p = lines_printed; - return SVN_NO_ERROR; } @@ -866,7 +860,7 @@ output_common_modified(void *baton, apr_off_t modified_start, apr_off_t modified_length, apr_off_t latest_start, apr_off_t latest_length) { - return output_merge_token_range(NULL, baton, 1/*modified*/, + return output_merge_token_range(baton, 1/*modified*/, modified_start, modified_length); } @@ -876,7 +870,7 @@ output_latest(void *baton, apr_off_t modified_start, apr_off_t modified_length, apr_off_t latest_start, apr_off_t latest_length) { - return output_merge_token_range(NULL, baton, 2/*latest*/, + return output_merge_token_range(baton, 2/*latest*/, latest_start, latest_length); } @@ -920,26 +914,26 @@ output_conflict(void *baton, style == svn_diff_conflict_display_modified_original_latest) { SVN_ERR(output_merge_marker(btn, 1/*modified*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/, + SVN_ERR(output_merge_token_range(btn, 1/*modified*/, modified_start, modified_length)); if (style == svn_diff_conflict_display_modified_original_latest) { SVN_ERR(output_merge_marker(btn, 0/*original*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/, + SVN_ERR(output_merge_token_range(btn, 0/*original*/, original_start, original_length)); } SVN_ERR(output_merge_marker(btn, 2/*separator*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/, + SVN_ERR(output_merge_token_range(btn, 2/*latest*/, latest_start, latest_length)); SVN_ERR(output_merge_marker(btn, 3/*latest (end)*/)); } else if (style == svn_diff_conflict_display_modified) - SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/, + SVN_ERR(output_merge_token_range(btn, 1/*modified*/, modified_start, modified_length)); else if (style == svn_diff_conflict_display_latest) - SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/, + SVN_ERR(output_merge_token_range(btn, 2/*latest*/, latest_start, latest_length)); else /* unknown style */ SVN_ERR_MALFUNCTION(); @@ -983,7 +977,7 @@ output_conflict_with_context(void *baton trailing context)? If so, flush it. */ if (btn->output_stream == btn->context_saver->stream) { - if (btn->context_saver->total_written > btn->context_size) + if (btn->context_saver->total_writes > btn->context_size) SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n")); SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream)); } @@ -995,17 +989,17 @@ output_conflict_with_context(void *baton SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[1], modified_start, modified_length)); - SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/, + SVN_ERR(output_merge_token_range(btn, 1/*modified*/, modified_start, modified_length)); SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[0], original_start, original_length)); - SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/, + SVN_ERR(output_merge_token_range(btn, 0/*original*/, original_start, original_length)); SVN_ERR(output_merge_marker(btn, 2/*separator*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/, + SVN_ERR(output_merge_token_range(btn, 2/*latest*/, latest_start, latest_length)); SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[3], latest_start, @@ -1066,7 +1060,7 @@ svn_diff_mem_string_output_merge3(svn_st svn_diff_conflict_display_style_t style, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { merge_output_baton_t btn; const char *eol; @@ -1080,16 +1074,16 @@ svn_diff_mem_string_output_merge3(svn_st if (conflicts_only) { - btn.pool = svn_pool_create(pool); + btn.pool = svn_pool_create(scratch_pool); make_context_saver(&btn); btn.real_output_stream = output_stream; } else btn.output_stream = output_stream; - fill_source_tokens(&(btn.sources[0]), original, pool); - fill_source_tokens(&(btn.sources[1]), modified, pool); - fill_source_tokens(&(btn.sources[2]), latest, pool); + fill_source_tokens(&(btn.sources[0]), original, scratch_pool); + fill_source_tokens(&(btn.sources[1]), modified, scratch_pool); + fill_source_tokens(&(btn.sources[2]), latest, scratch_pool); btn.conflict_style = style; @@ -1110,22 +1104,22 @@ svn_diff_mem_string_output_merge3(svn_st conflict_modified ? conflict_modified : "<<<<<<< (modified)", - pool)); + scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[0], conflict_original ? conflict_original : "||||||| (original)", - pool)); + scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[2], conflict_separator ? conflict_separator : "=======", - pool)); + scratch_pool)); SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[3], conflict_latest ? conflict_latest : ">>>>>>> (latest)", - pool)); + scratch_pool)); SVN_ERR(svn_diff_output2(diff, &btn, vtable, cancel_func, cancel_baton)); if (conflicts_only) Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c Sun Jun 14 20:58:10 2015 @@ -532,7 +532,7 @@ parse_mergeinfo(svn_boolean_t *found_mer } else SVN_ERR(err); - + if (mergeinfo) { if (hunk->original_length > 0) /* reverse merges */ Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs/editor.c Sun Jun 14 20:58:10 2015 @@ -249,7 +249,7 @@ can_modify(svn_fs_root_t *txn_root, svn_fs_close_root(rev_root); /* Has the target node changed in the future? */ - if (relation != svn_fs_node_same) + if (relation != svn_fs_node_unchanged) { /* Restarting the commit will base the txn on the future/new revision, allowing the modification at REVISION. */ @@ -777,16 +777,24 @@ svn_fs__editor_commit(svn_revnum_t *revi /* Clean up internal resources (eg. eb->root). This also allows the editor infrastructure to know this editor is "complete". */ err = svn_editor_complete(editor); + if (err) + { + svn_fs_txn_t *txn = eb->txn; + + eb->txn = NULL; + return svn_error_trace(svn_error_compose_create( + err, + svn_fs_abort_txn(txn, scratch_pool))); + } /* Note: docco for svn_fs_commit_txn() states that CONFLICT_PATH will be allocated in the txn's pool. But it lies. Regardless, we want it placed into RESULT_POOL. */ - if (!err) - err = svn_fs_commit_txn(&inner_conflict_path, - revision, - eb->txn, - scratch_pool); + err = svn_fs_commit_txn(&inner_conflict_path, + revision, + eb->txn, + scratch_pool); if (SVN_IS_VALID_REVNUM(*revision)) { if (err) Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.c Sun Jun 14 20:58:10 2015 @@ -27,7 +27,6 @@ #include <apr_atomic.h> #include <apr_hash.h> #include <apr_md5.h> -#include <apr_thread_mutex.h> #include <apr_uuid.h> #include <apr_strings.h> @@ -140,7 +139,7 @@ load_module(fs_init_func_t *initfunc, co _("Invalid name for FS type '%s'"), name); - libname = apr_psprintf(pool, "libsvn_fs_%s-%d.so.%d", + libname = apr_psprintf(pool, "libsvn_fs_%s-" SVN_DSO_SUFFIX_FMT, name, SVN_VER_MAJOR, SVN_SOVERSION); funcname = apr_psprintf(pool, "svn_fs_%s__init", name); @@ -408,6 +407,11 @@ synchronized_initialize(void *baton, apr svn_error_t * svn_fs_initialize(apr_pool_t *pool) { +#if defined(SVN_USE_DSO) && APR_HAS_DSO + /* Ensure that DSO subsystem is initialized early as possible if + we're going to use it. */ + SVN_ERR(svn_dso_initialize2()); +#endif /* Protect against multiple calls. */ return svn_error_trace(svn_atomic__init_once(&common_pool_initialized, synchronized_initialize, @@ -436,6 +440,8 @@ default_warning_func(void *baton, svn_er svn_error_t * svn_fs__path_valid(const char *path, apr_pool_t *pool) { + char *c; + /* UTF-8 encoded string without NULs. */ if (! svn_utf__cstring_is_valid(path)) { @@ -452,6 +458,18 @@ svn_fs__path_valid(const char *path, apr path); } + /* Raise an error if PATH contains a newline because svn:mergeinfo and + friends can't handle them. Issue #4340 describes a similar problem + in the FSFS code itself. + */ + c = strchr(path, '\n'); + if (c) + { + return svn_error_createf(SVN_ERR_FS_PATH_SYNTAX, NULL, + _("Invalid control character '0x%02x' in path '%s'"), + (unsigned char)*c, svn_path_illegal_path_escape(path, pool)); + } + /* That's good enough. */ return SVN_NO_ERROR; } @@ -542,19 +560,19 @@ svn_fs_upgrade2(const char *path, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { fs_library_vtable_t *vtable; svn_fs_t *fs; - SVN_ERR(fs_library_vtable(&vtable, path, pool)); - fs = fs_new(NULL, pool); + SVN_ERR(fs_library_vtable(&vtable, path, scratch_pool)); + fs = fs_new(NULL, scratch_pool); SVN_ERR(vtable->upgrade_fs(fs, path, notify_func, notify_baton, cancel_func, cancel_baton, common_pool_lock, - pool, common_pool)); + scratch_pool, common_pool)); return SVN_NO_ERROR; } @@ -897,26 +915,48 @@ svn_fs_list_transactions(apr_array_heade return svn_error_trace(fs->vtable->list_transactions(names_p, fs, pool)); } +static svn_boolean_t +is_internal_txn_prop(const char *name) +{ + return strcmp(name, SVN_FS__PROP_TXN_CHECK_LOCKS) == 0 || + strcmp(name, SVN_FS__PROP_TXN_CHECK_OOD) == 0 || + strcmp(name, SVN_FS__PROP_TXN_CLIENT_DATE) == 0; +} + svn_error_t * svn_fs_txn_prop(svn_string_t **value_p, svn_fs_txn_t *txn, const char *propname, apr_pool_t *pool) { + if (is_internal_txn_prop(propname)) + { + *value_p = NULL; + return SVN_NO_ERROR; + } + return svn_error_trace(txn->vtable->get_prop(value_p, txn, propname, pool)); } svn_error_t * svn_fs_txn_proplist(apr_hash_t **table_p, svn_fs_txn_t *txn, apr_pool_t *pool) { - return svn_error_trace(txn->vtable->get_proplist(table_p, txn, pool)); + SVN_ERR(txn->vtable->get_proplist(table_p, txn, pool)); + + /* Don't give away internal transaction properties. */ + svn_hash_sets(*table_p, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL); + svn_hash_sets(*table_p, SVN_FS__PROP_TXN_CHECK_OOD, NULL); + svn_hash_sets(*table_p, SVN_FS__PROP_TXN_CLIENT_DATE, NULL); + + return SVN_NO_ERROR; } svn_error_t * svn_fs_change_txn_prop(svn_fs_txn_t *txn, const char *name, const svn_string_t *value, apr_pool_t *pool) { - /* Silently drop attempts to modify the internal property. */ - if (!strcmp(name, SVN_FS__PROP_TXN_CLIENT_DATE)) - return SVN_NO_ERROR; + if (is_internal_txn_prop(name)) + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Attempt to modify internal transaction " + "property '%s'"), name); return svn_error_trace(txn->vtable->change_prop(txn, name, value, pool)); } @@ -927,25 +967,14 @@ svn_fs_change_txn_props(svn_fs_txn_t *tx { int i; - /* Silently drop attempts to modify the internal property. */ for (i = 0; i < props->nelts; ++i) { svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t); - if (!strcmp(prop->name, SVN_FS__PROP_TXN_CLIENT_DATE)) - { - apr_array_header_t *reduced_props - = apr_array_make(pool, props->nelts - 1, sizeof(svn_prop_t)); - - for (i = 0; i < props->nelts; ++i) - { - prop = &APR_ARRAY_IDX(props, i, svn_prop_t); - if (strcmp(prop->name, SVN_FS__PROP_TXN_CLIENT_DATE)) - APR_ARRAY_PUSH(reduced_props, svn_prop_t) = *prop; - } - props = reduced_props; - break; - } + if (is_internal_txn_prop(prop->name)) + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Attempt to modify internal transaction " + "property '%s'"), prop->name); } return svn_error_trace(txn->vtable->change_props(txn, props, pool)); @@ -1111,7 +1140,7 @@ svn_error_t * svn_fs_node_relation(svn_fs_node_relation_t *relation, svn_fs_root_t *root_a, const char *path_a, svn_fs_root_t *root_b, const char *path_b, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { /* Different repository types? */ if (root_a->fs != root_b->fs) @@ -1120,9 +1149,10 @@ svn_fs_node_relation(svn_fs_node_relatio return SVN_NO_ERROR; } - return svn_error_trace(root_a->vtable->node_relation(relation, root_a, - path_a, root_b, - path_b, pool)); + return svn_error_trace(root_a->vtable->node_relation(relation, + root_a, path_a, + root_b, path_b, + scratch_pool)); } svn_error_t * @@ -1166,6 +1196,16 @@ svn_fs_node_proplist(apr_hash_t **table_ } svn_error_t * +svn_fs_node_has_props(svn_boolean_t *has_props, + svn_fs_root_t *root, + const char *path, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(root->vtable->node_has_props(has_props, root, path, + scratch_pool)); +} + +svn_error_t * svn_fs_change_node_prop(svn_fs_root_t *root, const char *path, const char *name, const svn_string_t *value, apr_pool_t *pool) @@ -1177,12 +1217,12 @@ svn_fs_change_node_prop(svn_fs_root_t *r svn_error_t * svn_fs_props_different(svn_boolean_t *changed_p, svn_fs_root_t *root1, const char *path1, svn_fs_root_t *root2, - const char *path2, apr_pool_t *pool) + const char *path2, apr_pool_t *scratch_pool) { return svn_error_trace(root1->vtable->props_changed(changed_p, root1, path1, root2, path2, - TRUE, pool)); + TRUE, scratch_pool)); } svn_error_t * @@ -1290,10 +1330,13 @@ svn_error_t * svn_fs_dir_optimal_order(apr_array_header_t **ordered_p, svn_fs_root_t *root, apr_hash_t *entries, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { return svn_error_trace(root->vtable->dir_optimal_order(ordered_p, root, - entries, pool)); + entries, + result_pool, + scratch_pool)); } svn_error_t * @@ -1454,12 +1497,13 @@ svn_fs_apply_text(svn_stream_t **content svn_error_t * svn_fs_contents_different(svn_boolean_t *changed_p, svn_fs_root_t *root1, const char *path1, svn_fs_root_t *root2, - const char *path2, apr_pool_t *pool) + const char *path2, apr_pool_t *scratch_pool) { return svn_error_trace(root1->vtable->contents_changed(changed_p, root1, path1, root2, path2, - TRUE, pool)); + TRUE, + scratch_pool)); } svn_error_t * @@ -1617,20 +1661,24 @@ svn_fs_lock_many(svn_fs_t *fs, target->token, "opaquelocktoken"); if (!err) - for (c = target->token; *c && !err; c++) - if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c)) + { + for (c = target->token; *c && !err; c++) + if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c)) + err = svn_error_createf( + SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, + _("Lock token '%s' is not ASCII or is a " + "control character at byte %u"), + target->token, + (unsigned)(c - target->token)); + + /* strlen(token) == c - token. */ + if (!err && !svn_xml_is_xml_safe(target->token, + c - target->token)) err = svn_error_createf( - SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, - _("Lock token '%s' is not ASCII or is a " - "control character at byte %u"), - target->token, - (unsigned)(c - target->token)); - - /* strlen(token) == c - token. */ - if (!err && !svn_xml_is_xml_safe(target->token, c - target->token)) - err = svn_error_createf(SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, - _("Lock token URI '%s' is not XML-safe"), - target->token); + SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, + _("Lock token URI '%s' is not XML-safe"), + target->token); + } } if (err) @@ -1691,7 +1739,7 @@ svn_fs_lock(svn_lock_t **lock, svn_fs_t apr_pool_t *pool) { apr_hash_t *targets = apr_hash_make(pool); - svn_fs_lock_target_t target; + svn_fs_lock_target_t target; svn_error_t *err; struct lock_baton_t baton = {0}; @@ -1710,7 +1758,7 @@ svn_fs_lock(svn_lock_t **lock, svn_fs_t svn_error_compose(err, baton.fs_err); else if (!err) err = baton.fs_err; - + return svn_error_trace(err); } @@ -1723,9 +1771,10 @@ svn_fs_generate_lock_token(const char ** svn_fs_lock_target_t * svn_fs_lock_target_create(const char *token, svn_revnum_t current_rev, - apr_pool_t *pool) + apr_pool_t *result_pool) { - svn_fs_lock_target_t *target = apr_palloc(pool, sizeof(svn_fs_lock_target_t)); + svn_fs_lock_target_t *target = apr_palloc(result_pool, + sizeof(svn_fs_lock_target_t)); target->token = token; target->current_rev = current_rev; @@ -1863,7 +1912,7 @@ svn_fs_compare_ids(const svn_fs_id_t *a, { switch (a->vtable->compare(a, b)) { - case svn_fs_node_same: + case svn_fs_node_unchanged: return 0; case svn_fs_node_common_ancestor: return 1; @@ -1958,7 +2007,7 @@ svn_fs_info_dup(const void *info_void, fs_library_vtable_t *vtable; SVN_ERR(get_library_vtable(&vtable, info->fs_type, scratch_pool)); - + if (vtable->info_fsap_dup) return vtable->info_fsap_dup(info_void, result_pool); else Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs/fs-loader.h Sun Jun 14 20:58:10 2015 @@ -99,7 +99,7 @@ typedef struct fs_library_vtable_t svn_cancel_func_t cancel_func, void *cancel_baton, svn_mutex__t *common_pool_lock, - apr_pool_t *pool, + apr_pool_t *scratch_pool, apr_pool_t *common_pool); svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path, svn_revnum_t start, @@ -314,7 +314,7 @@ typedef struct root_vtable_t svn_error_t *(*node_relation)(svn_fs_node_relation_t *relation, svn_fs_root_t *root_a, const char *path_a, svn_fs_root_t *root_b, const char *path_b, - apr_pool_t *pool); + apr_pool_t *scratch_pool); svn_error_t *(*node_created_rev)(svn_revnum_t *revision, svn_fs_root_t *root, const char *path, apr_pool_t *pool); @@ -346,6 +346,8 @@ typedef struct root_vtable_t apr_pool_t *pool); svn_error_t *(*node_proplist)(apr_hash_t **table_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool); + svn_error_t *(*node_has_props)(svn_boolean_t *has_props, svn_fs_root_t *root, + const char *path, apr_pool_t *scratch_pool); svn_error_t *(*change_node_prop)(svn_fs_root_t *root, const char *path, const char *name, const svn_string_t *value, @@ -353,7 +355,7 @@ typedef struct root_vtable_t svn_error_t *(*props_changed)(int *changed_p, svn_fs_root_t *root1, const char *path1, svn_fs_root_t *root2, const char *path2, svn_boolean_t strict, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Directories */ svn_error_t *(*dir_entries)(apr_hash_t **entries_p, svn_fs_root_t *root, @@ -361,7 +363,8 @@ typedef struct root_vtable_t svn_error_t *(*dir_optimal_order)(apr_array_header_t **ordered_p, svn_fs_root_t *root, apr_hash_t *entries, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); svn_error_t *(*make_dir)(svn_fs_root_t *root, const char *path, apr_pool_t *pool); @@ -394,7 +397,7 @@ typedef struct root_vtable_t svn_error_t *(*contents_changed)(int *changed_p, svn_fs_root_t *root1, const char *path1, svn_fs_root_t *root2, const char *path2, svn_boolean_t strict, - apr_pool_t *pool); + apr_pool_t *scratch_pool); svn_error_t *(*get_file_delta_stream)(svn_txdelta_stream_t **stream_p, svn_fs_root_t *source_root, const char *source_path, @@ -446,7 +449,7 @@ typedef struct id_vtable_t /*** Definitions of the abstract FS object types ***/ /* These are transaction properties that correspond to the bitfields - in the 'flags' argument to svn_fs_lock(). */ + in the 'flags' argument to svn_fs_begin_txn2(). */ #define SVN_FS__PROP_TXN_CHECK_LOCKS SVN_PROP_PREFIX "check-locks" #define SVN_FS__PROP_TXN_CHECK_OOD SVN_PROP_PREFIX "check-ood" /* Set to "0" at the start of the txn, to "1" when svn:date changes. */ Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/bdb/rev-table.c Sun Jun 14 20:58:10 2015 @@ -79,6 +79,9 @@ svn_fs_bdb__get_rev(revision_t **revisio numbers begin with one. */ db_recno_t recno = (db_recno_t) rev + 1; + if (!SVN_IS_VALID_REVNUM(rev)) + return svn_fs_base__err_dangling_rev(fs, rev); + svn_fs_base__trail_debug(trail, "revisions", "get"); db_err = bfd->revisions->get(bfd->revisions, trail->db_txn, svn_fs_base__set_dbt(&key, &recno, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/fs.c Sun Jun 14 20:58:10 2015 @@ -780,7 +780,7 @@ base_create(svn_fs_t *fs, ((base_fs_data_t *) fs->fsap_data)->format = format; SVN_ERR(populate_opened_fs(fs, pool)); - return SVN_NO_ERROR;; + return SVN_NO_ERROR; error: return svn_error_compose_create(svn_err, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/id.c Sun Jun 14 20:58:10 2015 @@ -113,7 +113,7 @@ svn_fs_base__id_compare(const svn_fs_id_ const svn_fs_id_t *b) { if (svn_fs_base__id_eq(a, b)) - return svn_fs_node_same; + return svn_fs_node_unchanged; return (svn_fs_base__id_check_related(a, b) ? svn_fs_node_common_ancestor : svn_fs_node_unrelated); } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/lock.c Sun Jun 14 20:58:10 2015 @@ -39,6 +39,7 @@ #include "private/svn_fs_util.h" #include "private/svn_subr_private.h" #include "private/svn_dep_compat.h" +#include "revs-txns.h" /* Add LOCK and its associated LOCK_TOKEN (associated with PATH) as @@ -241,8 +242,11 @@ svn_fs_base__lock(svn_fs_t *fs, { apr_hash_index_t *hi; svn_error_t *cb_err = SVN_NO_ERROR; + svn_revnum_t youngest_rev = SVN_INVALID_REVNUM; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); SVN_ERR(svn_fs__check_fs(fs, TRUE)); + SVN_ERR(svn_fs_base__youngest_rev(&youngest_rev, fs, scratch_pool)); for (hi = apr_hash_first(scratch_pool, targets); hi; hi = apr_hash_next(hi)) { @@ -250,8 +254,9 @@ svn_fs_base__lock(svn_fs_t *fs, const char *path = apr_hash_this_key(hi); const svn_fs_lock_target_t *target = apr_hash_this_val(hi); svn_lock_t *lock; - svn_error_t *err; + svn_error_t *err = NULL; + svn_pool_clear(iterpool); args.lock_p = &lock; args.path = svn_fs__canonicalize_abspath(path, result_pool); args.token = target->token; @@ -261,13 +266,23 @@ svn_fs_base__lock(svn_fs_t *fs, args.expiration_date = expiration_date; args.current_rev = target->current_rev; args.result_pool = result_pool; - - err = svn_fs_base__retry_txn(fs, txn_body_lock, &args, TRUE, - scratch_pool); + + if (SVN_IS_VALID_REVNUM(target->current_rev)) + { + if (target->current_rev > youngest_rev) + err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), + target->current_rev); + } + + if (!err) + err = svn_fs_base__retry_txn(fs, txn_body_lock, &args, TRUE, + iterpool); if (!cb_err && lock_callback) - cb_err = lock_callback(lock_baton, args.path, lock, err, scratch_pool); + cb_err = lock_callback(lock_baton, args.path, lock, err, iterpool); svn_error_clear(err); } + svn_pool_destroy(iterpool); return svn_error_trace(cb_err); } @@ -356,6 +371,7 @@ svn_fs_base__unlock(svn_fs_t *fs, { apr_hash_index_t *hi; svn_error_t *cb_err = SVN_NO_ERROR; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); SVN_ERR(svn_fs__check_fs(fs, TRUE)); @@ -366,16 +382,18 @@ svn_fs_base__unlock(svn_fs_t *fs, const char *token = apr_hash_this_val(hi); svn_error_t *err; + svn_pool_clear(iterpool); args.path = svn_fs__canonicalize_abspath(path, result_pool); args.token = token; args.break_lock = break_lock; err = svn_fs_base__retry_txn(fs, txn_body_unlock, &args, TRUE, - scratch_pool); + iterpool); if (!cb_err && lock_callback) - cb_err = lock_callback(lock_baton, path, NULL, err, scratch_pool); + cb_err = lock_callback(lock_baton, path, NULL, err, iterpool); svn_error_clear(err); } + svn_pool_destroy(iterpool); return svn_error_trace(cb_err); } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c Sun Jun 14 20:58:10 2015 @@ -711,6 +711,23 @@ txn_body_begin_txn(void *baton, trail_t SVN_ERR(txn_body_change_txn_prop(&cpargs, trail)); } + /* Put a datestamp on the newly created txn, so we always know + exactly how old it is. (This will help sysadmins identify + long-abandoned txns that may need to be manually removed.) Do + this before setting CLIENT_DATE so that it is not recorded as an + explicit setting. */ + { + struct change_txn_prop_args cpargs; + svn_string_t date; + cpargs.fs = trail->fs; + cpargs.id = txn_id; + cpargs.name = SVN_PROP_REVISION_DATE; + date.data = svn_time_to_cstring(apr_time_now(), trail->pool); + date.len = strlen(date.data); + cpargs.value = &date; + SVN_ERR(txn_body_change_txn_prop(&cpargs, trail)); + } + if (args->flags & SVN_FS_TXN_CLIENT_DATE) { struct change_txn_prop_args cpargs; @@ -737,7 +754,6 @@ svn_fs_base__begin_txn(svn_fs_txn_t **tx { svn_fs_txn_t *txn; struct begin_txn_args args; - svn_string_t date; SVN_ERR(svn_fs__check_fs(fs, TRUE)); @@ -748,15 +764,7 @@ svn_fs_base__begin_txn(svn_fs_txn_t **tx *txn_p = txn; - /* Put a datestamp on the newly created txn, so we always know - exactly how old it is. (This will help sysadmins identify - long-abandoned txns that may need to be manually removed.) When - a txn is promoted to a revision, this property will be - automatically overwritten with a revision datestamp. */ - date.data = svn_time_to_cstring(apr_time_now(), pool); - date.len = strlen(date.data); - return svn_fs_base__change_txn_prop(txn, SVN_PROP_REVISION_DATE, - &date, pool); + return SVN_NO_ERROR; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/tree.c Sun Jun 14 20:58:10 2015 @@ -1285,6 +1285,21 @@ base_node_proplist(apr_hash_t **table_p, return SVN_NO_ERROR; } +static svn_error_t * +base_node_has_props(svn_boolean_t *has_props, + svn_fs_root_t *root, + const char *path, + apr_pool_t *scratch_pool) +{ + apr_hash_t *props; + + SVN_ERR(base_node_proplist(&props, root, path, scratch_pool)); + + *has_props = (0 < apr_hash_count(props)); + + return SVN_NO_ERROR; +} + struct change_node_prop_args { svn_fs_root_t *root; @@ -1608,13 +1623,15 @@ static svn_error_t * base_dir_optimal_order(apr_array_header_t **ordered_p, svn_fs_root_t *root, apr_hash_t *entries, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { /* 1:1 copy of entries with no differnce in ordering */ apr_hash_index_t *hi; - apr_array_header_t *result = apr_array_make(pool, apr_hash_count(entries), - sizeof(svn_fs_dirent_t *)); - for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi)) + apr_array_header_t *result + = apr_array_make(result_pool, apr_hash_count(entries), + sizeof(svn_fs_dirent_t *)); + for (hi = apr_hash_first(scratch_pool, entries); hi; hi = apr_hash_next(hi)) APR_ARRAY_PUSH(result, svn_fs_dirent_t *) = apr_hash_this_val(hi); *ordered_p = result; @@ -3164,7 +3181,8 @@ txn_body_copy(void *baton, if ((to_parent_path->node) && (svn_fs_base__id_compare(svn_fs_base__dag_get_id(from_node), svn_fs_base__dag_get_id - (to_parent_path->node)) == svn_fs_node_same)) + (to_parent_path->node)) + == svn_fs_node_unchanged)) return SVN_NO_ERROR; if (! from_root->is_txn_root) @@ -5489,6 +5507,7 @@ static root_vtable_t root_vtable = { base_closest_copy, base_node_prop, base_node_proplist, + base_node_has_props, base_change_node_prop, base_props_changed, base_dir_entries,
