Merge ^/head r286422 through r286684.

This commit is contained in:
Dimitry Andric 2015-08-12 18:39:49 +00:00
commit f98ee84465
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang-trunk/; revision=286685
494 changed files with 92757 additions and 15225 deletions

View File

@ -807,7 +807,7 @@ __installcheck_UGID:
_zoneinfo= zic tzsetup
.endif
ITOOLS= [ awk cap_mkdb cat chflags chmod chown \
ITOOLS= [ awk cap_mkdb cat chflags chmod chown cmp cp \
date echo egrep find grep id install ${_install-info} \
ln lockf make mkdir mtree mv pwd_mkdb \
rm sed services_mkdb sh strip sysctl test true uname wc ${_zoneinfo} \
@ -1225,16 +1225,23 @@ update:
#
#
# legacy: Build compatibility shims for the next three targets. This is a minimal
# set of tools and shims necessary to compensate for older systems which don't have
# the APIs that the targets built in bootstrap-tools, build-tools or cross-tools.
# legacy: Build compatibility shims for the next three targets. This is a
# minimal set of tools and shims necessary to compensate for older systems
# which don't have the APIs required by the targets built in bootstrap-tools,
# build-tools or cross-tools.
#
# ELF Tool Chain libraries are needed for ELF tools and dtrace tools.
.if ${BOOTSTRAPPING} < 1100006
_elftoolchain_libs= lib/libelf lib/libdwarf
.endif
legacy:
.if ${BOOTSTRAPPING} < 800107 && ${BOOTSTRAPPING} != 0
@echo "ERROR: Source upgrades from versions prior to 8.0 not supported."; \
false
.endif
.for _tool in tools/build
.for _tool in tools/build ${_elftoolchain_libs}
${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,depend,all,install)"; \
cd ${.CURDIR}/${_tool} && \
${MAKE} DIRPRFX=${_tool}/ obj && \
@ -1297,7 +1304,8 @@ _lex= usr.bin/lex
# r277259 crunchide: Correct 64-bit section header offset
# r281674 crunchide: always include both 32- and 64-bit ELF support
.if ${BOOTSTRAPPING} < 1100071
# r285986 crunchen: use STRIPBIN rather than STRIP
.if ${BOOTSTRAPPING} < 1100078
_crunch= usr.sbin/crunch
.endif
@ -1332,13 +1340,12 @@ ${_bt}-usr.bin/clang/tblgen: ${_bt}-lib/clang/libllvmtablegen ${_bt}-lib/clang/l
# pre libdwarf
.if ${BOOTSTRAPPING} < 1100006 || (${MACHINE} != ${TARGET} || \
${MACHINE_ARCH} != ${TARGET_ARCH})
_elftoolchain_libs= lib/libelf lib/libdwarf
.if ${MK_CDDL} != "no"
_dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf cddl/usr.bin/ctfconvert \
cddl/usr.bin/ctfmerge
${_bt}-cddl/usr.bin/ctfconvert: ${_bt}-lib/libelf ${_bt}-lib/libdwarf ${_bt}-cddl/lib/libctf
${_bt}-cddl/usr.bin/ctfmerge: ${_bt}-lib/libelf ${_bt}-lib/libdwarf ${_bt}-cddl/lib/libctf
${_bt}-cddl/usr.bin/ctfconvert: ${_bt}-cddl/lib/libctf
${_bt}-cddl/usr.bin/ctfmerge: ${_bt}-cddl/lib/libctf
.endif
.endif
@ -1381,7 +1388,6 @@ bootstrap-tools: .PHONY
.for _tool in \
${_clang_tblgen} \
${_kerberos5_bootstrap_tools} \
${_elftoolchain_libs} \
${_dtrace_tools} \
${_strfile} \
${_gperf} \
@ -1426,15 +1432,10 @@ _share= share/syscons/scrnmaps
_gcc_tools= gnu/usr.bin/cc/cc_tools
.endif
.if ${MK_RESCUE} != "no"
_rescue= rescue/rescue
.endif
build-tools: .MAKE
.for _tool in \
bin/csh \
bin/sh \
${_rescue} \
${LOCAL_TOOL_DIRS} \
lib/ncurses/ncurses \
lib/ncurses/ncursesw \

View File

@ -36,6 +36,28 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
20141231 entry below for information about prerequisites and upgrading,
if you are not already using 3.5.0 or higher.
20150810:
The polarity of Pulse Per Second (PPS) capture events with the
uart(4) driver has been corrected. Prior to this change the PPS
"assert" event corresponded to the trailing edge of a positive PPS
pulse and the "clear" event was the leading edge of the next pulse.
As the width of a PPS pulse in a typical GPS receiver is on the
order of 1 millisecond, most users will not notice any significant
difference with this change.
Anyone who has compensated for the historical polarity reversal by
configuring a negative offset equal to the pulse width will need to
remove that workaround.
20150809:
The default group assigned to /dev/dri entries has been changed
from 'wheel' to 'video' with the id of '44'. If you want to have
access to the dri devices please add yourself to the video group
with:
# pw groupmod video -m $USER
20150806:
The menu.rc and loader.rc files will now be replaced during
upgrades. Please migrate local changes to menu.rc.local and

View File

@ -95,6 +95,8 @@ static int zopt_objects = 0;
static libzfs_handle_t *g_zfs;
static uint64_t max_inflight = 1000;
static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *);
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
* debugging facilities.
@ -418,6 +420,79 @@ dump_zap(objset_t *os, uint64_t object, void *data, size_t size)
zap_cursor_fini(&zc);
}
static void
dump_bpobj(objset_t *os, uint64_t object, void *data, size_t size)
{
bpobj_phys_t *bpop = data;
char bytes[32], comp[32], uncomp[32];
if (bpop == NULL)
return;
zdb_nicenum(bpop->bpo_bytes, bytes);
zdb_nicenum(bpop->bpo_comp, comp);
zdb_nicenum(bpop->bpo_uncomp, uncomp);
(void) printf("\t\tnum_blkptrs = %llu\n",
(u_longlong_t)bpop->bpo_num_blkptrs);
(void) printf("\t\tbytes = %s\n", bytes);
if (size >= BPOBJ_SIZE_V1) {
(void) printf("\t\tcomp = %s\n", comp);
(void) printf("\t\tuncomp = %s\n", uncomp);
}
if (size >= sizeof (*bpop)) {
(void) printf("\t\tsubobjs = %llu\n",
(u_longlong_t)bpop->bpo_subobjs);
(void) printf("\t\tnum_subobjs = %llu\n",
(u_longlong_t)bpop->bpo_num_subobjs);
}
if (dump_opt['d'] < 5)
return;
for (uint64_t i = 0; i < bpop->bpo_num_blkptrs; i++) {
char blkbuf[BP_SPRINTF_LEN];
blkptr_t bp;
int err = dmu_read(os, object,
i * sizeof (bp), sizeof (bp), &bp, 0);
if (err != 0) {
(void) printf("got error %u from dmu_read\n", err);
break;
}
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), &bp);
(void) printf("\t%s\n", blkbuf);
}
}
/* ARGSUSED */
static void
dump_bpobj_subobjs(objset_t *os, uint64_t object, void *data, size_t size)
{
dmu_object_info_t doi;
VERIFY0(dmu_object_info(os, object, &doi));
uint64_t *subobjs = kmem_alloc(doi.doi_max_offset, KM_SLEEP);
int err = dmu_read(os, object, 0, doi.doi_max_offset, subobjs, 0);
if (err != 0) {
(void) printf("got error %u from dmu_read\n", err);
kmem_free(subobjs, doi.doi_max_offset);
return;
}
int64_t last_nonzero = -1;
for (uint64_t i = 0; i < doi.doi_max_offset / 8; i++) {
if (subobjs[i] != 0)
last_nonzero = i;
}
for (int64_t i = 0; i <= last_nonzero; i++) {
(void) printf("\t%llu\n", (longlong_t)subobjs[i]);
}
kmem_free(subobjs, doi.doi_max_offset);
}
/*ARGSUSED*/
static void
dump_ddt_zap(objset_t *os, uint64_t object, void *data, size_t size)
@ -1397,7 +1472,7 @@ dump_bpobj_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
}
static void
dump_bpobj(bpobj_t *bpo, char *name, int indent)
dump_full_bpobj(bpobj_t *bpo, char *name, int indent)
{
char bytes[32];
char comp[32];
@ -1411,11 +1486,12 @@ dump_bpobj(bpobj_t *bpo, char *name, int indent)
zdb_nicenum(bpo->bpo_phys->bpo_comp, comp);
zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp);
(void) printf(" %*s: object %llu, %llu local blkptrs, "
"%llu subobjs, %s (%s/%s comp)\n",
"%llu subobjs in object %llu, %s (%s/%s comp)\n",
indent * 8, name,
(u_longlong_t)bpo->bpo_object,
(u_longlong_t)bpo->bpo_phys->bpo_num_blkptrs,
(u_longlong_t)bpo->bpo_phys->bpo_num_subobjs,
(u_longlong_t)bpo->bpo_phys->bpo_subobjs,
bytes, comp, uncomp);
for (uint64_t i = 0; i < bpo->bpo_phys->bpo_num_subobjs; i++) {
@ -1432,7 +1508,7 @@ dump_bpobj(bpobj_t *bpo, char *name, int indent)
error, (u_longlong_t)subobj);
continue;
}
dump_bpobj(&subbpo, "subobj", indent + 1);
dump_full_bpobj(&subbpo, "subobj", indent + 1);
bpobj_close(&subbpo);
}
} else {
@ -1466,7 +1542,7 @@ dump_deadlist(dsl_deadlist_t *dl)
return;
if (dl->dl_oldfmt) {
dump_bpobj(&dl->dl_bpobj, "old-format deadlist", 0);
dump_full_bpobj(&dl->dl_bpobj, "old-format deadlist", 0);
return;
}
@ -1491,7 +1567,7 @@ dump_deadlist(dsl_deadlist_t *dl)
(void) snprintf(buf, sizeof (buf), "mintxg %llu -> "
"obj %llu", (longlong_t)dle->dle_mintxg,
(longlong_t)dle->dle_bpobj.bpo_object);
dump_bpobj(&dle->dle_bpobj, buf, 0);
dump_full_bpobj(&dle->dle_bpobj, buf, 0);
} else {
(void) printf("mintxg %llu -> obj %llu\n",
(longlong_t)dle->dle_mintxg,
@ -1682,8 +1758,8 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
dump_uint64, /* object array */
dump_none, /* packed nvlist */
dump_packed_nvlist, /* packed nvlist size */
dump_none, /* bplist */
dump_none, /* bplist header */
dump_none, /* bpobj */
dump_bpobj, /* bpobj header */
dump_none, /* SPA space map header */
dump_none, /* SPA space map */
dump_none, /* ZIL intent log */
@ -1730,7 +1806,7 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
dump_zap, /* deadlist */
dump_none, /* deadlist hdr */
dump_zap, /* dsl clones */
dump_none, /* bpobj subobjs */
dump_bpobj_subobjs, /* bpobj subobjs */
dump_unknown, /* Unknown type, must be last */
};
@ -2959,10 +3035,11 @@ dump_zpool(spa_t *spa)
uint64_t refcount;
dump_dir(dp->dp_meta_objset);
if (dump_opt['d'] >= 3) {
dump_bpobj(&spa->spa_deferred_bpobj,
dump_full_bpobj(&spa->spa_deferred_bpobj,
"Deferred frees", 0);
if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
dump_bpobj(&spa->spa_dsl_pool->dp_free_bpobj,
dump_full_bpobj(
&spa->spa_dsl_pool->dp_free_bpobj,
"Pool snapshot frees", 0);
}

View File

@ -939,7 +939,23 @@ Disabling checksums is
.Em NOT
a recommended practice.
.It Sy compression Ns = Ns Cm on | off | lzjb | gzip | gzip- Ns Ar N | Cm zle | Cm lz4
Controls the compression algorithm used for this dataset. The
Controls the compression algorithm used for this dataset.
Setting compression to
.Cm on
indicates that the current default compression algorithm should be used.
The default balances compression and decompression speed, with compression
ratio and is expected to work well on a wide variety of workloads.
Unlike all other settings for this property, on does not select a fixed
compression type.
As new compression algorithms are added to ZFS and enabled on a pool, the
default compression algorithm may change.
The current default compression algorthm is either
.Cm lzjb
or, if the
.Sy lz4_compress
feature is enabled,
.Cm lz4 .
The
.Cm lzjb
compression algorithm is optimized for performance while providing decent data
compression. Setting compression to

View File

@ -25,7 +25,7 @@
*/
/*
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013, 2014 by Delphix. All rights reserved.
*/
#include <ctype.h>
@ -34,6 +34,7 @@
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/dmu.h>
#include <sys/zfs_ioctl.h>
@ -83,7 +84,6 @@ safe_malloc(size_t size)
*
* Read while computing incremental checksum
*/
static size_t
ssread(void *buf, size_t len, zio_cksum_t *cksum)
{
@ -92,7 +92,7 @@ ssread(void *buf, size_t len, zio_cksum_t *cksum)
if ((outlen = fread(buf, len, 1, send_stream)) == 0)
return (0);
if (do_cksum && cksum) {
if (do_cksum) {
if (do_byteswap)
fletcher_4_incremental_byteswap(buf, len, cksum);
else
@ -102,6 +102,34 @@ ssread(void *buf, size_t len, zio_cksum_t *cksum)
return (outlen);
}
static size_t
read_hdr(dmu_replay_record_t *drr, zio_cksum_t *cksum)
{
ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
size_t r = ssread(drr, sizeof (*drr) - sizeof (zio_cksum_t), cksum);
if (r == 0)
return (0);
zio_cksum_t saved_cksum = *cksum;
r = ssread(&drr->drr_u.drr_checksum.drr_checksum,
sizeof (zio_cksum_t), cksum);
if (r == 0)
return (0);
if (!ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.drr_checksum.drr_checksum) &&
!ZIO_CHECKSUM_EQUAL(saved_cksum,
drr->drr_u.drr_checksum.drr_checksum)) {
fprintf(stderr, "invalid checksum\n");
(void) printf("Incorrect checksum in record header.\n");
(void) printf("Expected checksum = %llx/%llx/%llx/%llx\n",
saved_cksum.zc_word[0],
saved_cksum.zc_word[1],
saved_cksum.zc_word[2],
saved_cksum.zc_word[3]);
exit(1);
}
return (sizeof (*drr));
}
/*
* Print part of a block in ASCII characters
*/
@ -183,8 +211,10 @@ main(int argc, char *argv[])
struct drr_free *drrf = &thedrr.drr_u.drr_free;
struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;
struct drr_checksum *drrc = &thedrr.drr_u.drr_checksum;
char c;
boolean_t verbose = B_FALSE;
boolean_t very_verbose = B_FALSE;
boolean_t first = B_TRUE;
/*
* dump flag controls whether the contents of any modified data blocks
@ -202,11 +232,14 @@ main(int argc, char *argv[])
do_cksum = B_FALSE;
break;
case 'v':
if (verbose)
very_verbose = B_TRUE;
verbose = B_TRUE;
break;
case 'd':
dump = B_TRUE;
verbose = B_TRUE;
very_verbose = B_TRUE;
break;
case ':':
(void) fprintf(stderr,
@ -230,7 +263,7 @@ main(int argc, char *argv[])
send_stream = stdin;
pcksum = zc;
while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) {
while (read_hdr(drr, &zc)) {
/*
* If this is the first DMU record being processed, check for
@ -432,7 +465,7 @@ main(int argc, char *argv[])
if (verbose) {
(void) printf("WRITE object = %llu type = %u "
"checksum type = %u\n"
"offset = %llu length = %llu "
" offset = %llu length = %llu "
"props = %llx\n",
(u_longlong_t)drrw->drr_object,
drrw->drr_type,
@ -476,9 +509,9 @@ main(int argc, char *argv[])
if (verbose) {
(void) printf("WRITE_BYREF object = %llu "
"checksum type = %u props = %llx\n"
"offset = %llu length = %llu\n"
" offset = %llu length = %llu\n"
"toguid = %llx refguid = %llx\n"
"refobject = %llu refoffset = %llu\n",
" refobject = %llu refoffset = %llu\n",
(u_longlong_t)drrwbr->drr_object,
drrwbr->drr_checksumtype,
(u_longlong_t)drrwbr->drr_key.ddk_prop,
@ -538,7 +571,7 @@ main(int argc, char *argv[])
if (verbose) {
(void) printf("WRITE_EMBEDDED object = %llu "
"offset = %llu length = %llu\n"
"toguid = %llx comp = %u etype = %u "
" toguid = %llx comp = %u etype = %u "
"lsize = %u psize = %u\n",
(u_longlong_t)drrwe->drr_object,
(u_longlong_t)drrwe->drr_offset,
@ -553,6 +586,13 @@ main(int argc, char *argv[])
P2ROUNDUP(drrwe->drr_psize, 8), &zc);
break;
}
if (drr->drr_type != DRR_BEGIN && very_verbose) {
(void) printf(" checksum = %llx/%llx/%llx/%llx\n",
(longlong_t)drrc->drr_checksum.zc_word[0],
(longlong_t)drrc->drr_checksum.zc_word[1],
(longlong_t)drrc->drr_checksum.zc_word[2],
(longlong_t)drrc->drr_checksum.zc_word[3]);
}
pcksum = zc;
}
free(buf);

View File

@ -188,10 +188,28 @@ ddt_update(libzfs_handle_t *hdl, dedup_table_t *ddt, zio_cksum_t *cs,
}
static int
cksum_and_write(const void *buf, uint64_t len, zio_cksum_t *zc, int outfd)
dump_record(dmu_replay_record_t *drr, void *payload, int payload_len,
zio_cksum_t *zc, int outfd)
{
fletcher_4_incremental_native(buf, len, zc);
return (write(outfd, buf, len));
ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
fletcher_4_incremental_native(drr,
offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc);
if (drr->drr_type != DRR_BEGIN) {
ASSERT(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.
drr_checksum.drr_checksum));
drr->drr_u.drr_checksum.drr_checksum = *zc;
}
fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum,
sizeof (zio_cksum_t), zc);
if (write(outfd, drr, sizeof (*drr)) == -1)
return (errno);
if (payload_len != 0) {
fletcher_4_incremental_native(payload, payload_len, zc);
if (write(outfd, payload, payload_len) == -1)
return (errno);
}
return (0);
}
/*
@ -218,26 +236,18 @@ cksummer(void *arg)
char *buf = zfs_alloc(dda->dedup_hdl, SPA_MAXBLOCKSIZE);
dmu_replay_record_t thedrr;
dmu_replay_record_t *drr = &thedrr;
struct drr_begin *drrb = &thedrr.drr_u.drr_begin;
struct drr_end *drre = &thedrr.drr_u.drr_end;
struct drr_object *drro = &thedrr.drr_u.drr_object;
struct drr_write *drrw = &thedrr.drr_u.drr_write;
struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;
FILE *ofp;
int outfd;
dmu_replay_record_t wbr_drr = {0};
struct drr_write_byref *wbr_drrr = &wbr_drr.drr_u.drr_write_byref;
dedup_table_t ddt;
zio_cksum_t stream_cksum;
uint64_t physmem = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE);
uint64_t numbuckets;
ddt.max_ddt_size =
MAX((physmem * MAX_DDT_PHYSMEM_PERCENT)/100,
SMALLEST_POSSIBLE_MAX_DDT_MB<<20);
MAX((physmem * MAX_DDT_PHYSMEM_PERCENT) / 100,
SMALLEST_POSSIBLE_MAX_DDT_MB << 20);
numbuckets = ddt.max_ddt_size/(sizeof (dedup_entry_t));
numbuckets = ddt.max_ddt_size / (sizeof (dedup_entry_t));
/*
* numbuckets must be a power of 2. Increase number to
@ -253,32 +263,29 @@ cksummer(void *arg)
ddt.numhashbits = high_order_bit(numbuckets) - 1;
ddt.ddt_full = B_FALSE;
/* Initialize the write-by-reference block. */
wbr_drr.drr_type = DRR_WRITE_BYREF;
wbr_drr.drr_payloadlen = 0;
outfd = dda->outputfd;
ofp = fdopen(dda->inputfd, "r");
while (ssread(drr, sizeof (dmu_replay_record_t), ofp) != 0) {
while (ssread(drr, sizeof (*drr), ofp) != 0) {
switch (drr->drr_type) {
case DRR_BEGIN:
{
int fflags;
struct drr_begin *drrb = &drr->drr_u.drr_begin;
int fflags;
int sz = 0;
ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0);
ASSERT3U(drrb->drr_magic, ==, DMU_BACKUP_MAGIC);
/* set the DEDUP feature flag for this stream */
fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
fflags |= (DMU_BACKUP_FEATURE_DEDUP |
DMU_BACKUP_FEATURE_DEDUPPROPS);
DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags);
if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
&stream_cksum, outfd) == -1)
goto out;
if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
DMU_COMPOUNDSTREAM && drr->drr_payloadlen != 0) {
int sz = drr->drr_payloadlen;
sz = drr->drr_payloadlen;
if (sz > SPA_MAXBLOCKSIZE) {
buf = zfs_realloc(dda->dedup_hdl, buf,
@ -287,64 +294,60 @@ cksummer(void *arg)
(void) ssread(buf, sz, ofp);
if (ferror(stdin))
perror("fread");
if (cksum_and_write(buf, sz, &stream_cksum,
outfd) == -1)
goto out;
}
if (dump_record(drr, buf, sz, &stream_cksum,
outfd) != 0)
goto out;
break;
}
case DRR_END:
{
struct drr_end *drre = &drr->drr_u.drr_end;
/* use the recalculated checksum */
ZIO_SET_CHECKSUM(&drre->drr_checksum,
stream_cksum.zc_word[0], stream_cksum.zc_word[1],
stream_cksum.zc_word[2], stream_cksum.zc_word[3]);
if ((write(outfd, drr,
sizeof (dmu_replay_record_t))) == -1)
drre->drr_checksum = stream_cksum;
if (dump_record(drr, NULL, 0, &stream_cksum,
outfd) != 0)
goto out;
break;
}
case DRR_OBJECT:
{
if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
&stream_cksum, outfd) == -1)
goto out;
struct drr_object *drro = &drr->drr_u.drr_object;
if (drro->drr_bonuslen > 0) {
(void) ssread(buf,
P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
ofp);
if (cksum_and_write(buf,
P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
&stream_cksum, outfd) == -1)
goto out;
}
if (dump_record(drr, buf,
P2ROUNDUP((uint64_t)drro->drr_bonuslen, 8),
&stream_cksum, outfd) != 0)
goto out;
break;
}
case DRR_SPILL:
{
if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
&stream_cksum, outfd) == -1)
goto out;
struct drr_spill *drrs = &drr->drr_u.drr_spill;
(void) ssread(buf, drrs->drr_length, ofp);
if (cksum_and_write(buf, drrs->drr_length,
&stream_cksum, outfd) == -1)
if (dump_record(drr, buf, drrs->drr_length,
&stream_cksum, outfd) != 0)
goto out;
break;
}
case DRR_FREEOBJECTS:
{
if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
&stream_cksum, outfd) == -1)
if (dump_record(drr, NULL, 0, &stream_cksum,
outfd) != 0)
goto out;
break;
}
case DRR_WRITE:
{
struct drr_write *drrw = &drr->drr_u.drr_write;
dataref_t dataref;
(void) ssread(buf, drrw->drr_length, ofp);
@ -382,7 +385,13 @@ cksummer(void *arg)
if (ddt_update(dda->dedup_hdl, &ddt,
&drrw->drr_key.ddk_cksum, drrw->drr_key.ddk_prop,
&dataref)) {
dmu_replay_record_t wbr_drr = {0};
struct drr_write_byref *wbr_drrr =
&wbr_drr.drr_u.drr_write_byref;
/* block already present in stream */
wbr_drr.drr_type = DRR_WRITE_BYREF;
wbr_drrr->drr_object = drrw->drr_object;
wbr_drrr->drr_offset = drrw->drr_offset;
wbr_drrr->drr_length = drrw->drr_length;
@ -402,19 +411,13 @@ cksummer(void *arg)
wbr_drrr->drr_key.ddk_prop =
drrw->drr_key.ddk_prop;
if (cksum_and_write(&wbr_drr,
sizeof (dmu_replay_record_t), &stream_cksum,
outfd) == -1)
if (dump_record(&wbr_drr, NULL, 0,
&stream_cksum, outfd) != 0)
goto out;
} else {
/* block not previously seen */
if (cksum_and_write(drr,
sizeof (dmu_replay_record_t), &stream_cksum,
outfd) == -1)
goto out;
if (cksum_and_write(buf,
drrw->drr_length,
&stream_cksum, outfd) == -1)
if (dump_record(drr, buf, drrw->drr_length,
&stream_cksum, outfd) != 0)
goto out;
}
break;
@ -422,28 +425,27 @@ cksummer(void *arg)
case DRR_WRITE_EMBEDDED:
{
if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
&stream_cksum, outfd) == -1)
goto out;
struct drr_write_embedded *drrwe =
&drr->drr_u.drr_write_embedded;
(void) ssread(buf,
P2ROUNDUP((uint64_t)drrwe->drr_psize, 8), ofp);
if (cksum_and_write(buf,
if (dump_record(drr, buf,
P2ROUNDUP((uint64_t)drrwe->drr_psize, 8),
&stream_cksum, outfd) == -1)
&stream_cksum, outfd) != 0)
goto out;
break;
}
case DRR_FREE:
{
if (cksum_and_write(drr, sizeof (dmu_replay_record_t),
&stream_cksum, outfd) == -1)
if (dump_record(drr, NULL, 0, &stream_cksum,
outfd) != 0)
goto out;
break;
}
default:
(void) printf("INVALID record type 0x%x\n",
(void) fprintf(stderr, "INVALID record type 0x%x\n",
drr->drr_type);
/* should never happen, so assert */
assert(B_FALSE);
@ -1470,18 +1472,11 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
sizeof (drr.drr_u.drr_begin.drr_toname),
"%s@%s", zhp->zfs_name, tosnap);
drr.drr_payloadlen = buflen;
err = cksum_and_write(&drr, sizeof (drr), &zc, outfd);
/* write header nvlist */
if (err != -1 && packbuf != NULL) {
err = cksum_and_write(packbuf, buflen, &zc,
outfd);
}
err = dump_record(&drr, packbuf, buflen, &zc, outfd);
free(packbuf);
if (err == -1) {
err = errno;
if (err != 0)
goto stderr_out;
}
/* write end record */
bzero(&drr, sizeof (drr));
@ -1714,6 +1709,8 @@ recv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen,
int rv;
int len = ilen;
assert(ilen <= SPA_MAXBLOCKSIZE);
do {
rv = read(fd, cp, len);
cp += rv;

View File

@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
@ -532,18 +532,30 @@ lzc_send(const char *snapname, const char *from, int fd,
}
/*
* If fromsnap is NULL, a full (non-incremental) stream will be estimated.
* "from" can be NULL, a snapshot, or a bookmark.
*
* If from is NULL, a full (non-incremental) stream will be estimated. This
* is calculated very efficiently.
*
* If from is a snapshot, lzc_send_space uses the deadlists attached to
* each snapshot to efficiently estimate the stream size.
*
* If from is a bookmark, the indirect blocks in the destination snapshot
* are traversed, looking for blocks with a birth time since the creation TXG of
* the snapshot this bookmark was created from. This will result in
* significantly more I/O and be less efficient than a send space estimation on
* an equivalent snapshot.
*/
int
lzc_send_space(const char *snapname, const char *fromsnap, uint64_t *spacep)
lzc_send_space(const char *snapname, const char *from, uint64_t *spacep)
{
nvlist_t *args;
nvlist_t *result;
int err;
args = fnvlist_alloc();
if (fromsnap != NULL)
fnvlist_add_string(args, "fromsnap", fromsnap);
if (from != NULL)
fnvlist_add_string(args, "from", from);
err = lzc_ioctl(ZFS_IOC_SEND_SPACE, snapname, args, &result);
nvlist_free(args);
if (err == 0)

View File

@ -1,4 +1,63 @@
-*- coding: utf-8 -*-
Changes for APR 1.5.2
*) SECURITY: CVE-2015-1829 (cve.mitre.org)
APR applications using APR named pipe support on Windows can be
vulnerable to a pipe squatting attack from a local process; the extent
of the vulnerability, when present, depends on the application.
Initial analysis and report was provided by John Hernandez of Casaba
Security via HP SSRT Security Alert. [Yann Ylavic]
*) apr_atomic: Fix errors when building on Visual Studio 2013 while
maintaining the ability to build on Visual Studio 6 with Windows
Server 2003 R2 SDK. PR 57191. [Gregg Smith]
*) Switch to generic atomics for early/unpatched Solaris 10 not exporting
some atomic functions. PR 55418. [Yann Ylavic]
*) apr_file_mktemp() on HP-UX: Remove limitation of 26 temporary files
per process. PR 57677. [Jeff Trawick]
*) apr_escape: Correctly calculate the size of the returned string in
apr_escape_path and set the correct return value in case we actually
escape the string. [<aduryagin gmail.com>] PR 57230.
*) pollcb on Windows: Handle calls with no file/socket descriptors.
Follow up to PR 49882. [Jeff Trawick, Yann Ylavic]
*) apr_poll(cb): fix error paths returned values and leaks. [Yann Ylavic]
*) apr_thread_cond_*wait() on BeOS: Fix broken logic. PR 45800.
[Jochen Voss (no e-mail)]
*) apr_skiplist: Optimize the number of allocations by reusing pooled or
malloc()ed nodes for the lifetime of the skiplist. [Yann Ylavic]
*) apr_skiplist: Fix possible multiple-free() on the same value in
apr_skiplist_remove_all(). [Yann Ylavic]
*) apr_pollset: On z/OS, threadsafe apr_pollset_poll() may return
"EDC8102I Operation would block" under load.
[Pat Odonnell <patod us.ibm.com>]
*) On z/OS, apr_sockaddr_info_get() with family == APR_UNSPEC was not
returning IPv4 addresses if any IPv6 addresses were returned.
[Eric Covener]
*) Windows cmake build: Fix an incompatibility with cmake 2.8.12 and
later. [Jeff Trawick]
*) apr_global_mutex/apr_proc_mutex: Resolve failures with the
POSIX sem implementation in environments which receive signals.
[Jeff Trawick]
*) apr_skiplist: Fix potential corruption of skiplists leading to
results or crashes. [Takashi Sato <takashi tks st>, Eric Covener]
PR 56654.
*) Improve platform detection by updating config.guess and config.sub.
[Rainer Jung]
Changes for APR 1.5.1
*) apr_os_proc_mutex_get() on Unix: Avoid segfault for cross-
@ -37,8 +96,8 @@ Changes for APR 1.5.1
*) Correct a regression in 1.5.0 which affected out-of-tree
builds on Unix. [Rainer Jung]
*) Improve platform detection for bundled expat by updating
config.guess and config.sub. [Rainer Jung]
*) Improve platform detection by updating config.guess and config.sub.
[Rainer Jung]
Changes for APR 1.5.0

View File

@ -234,6 +234,7 @@ SET(APR_TEST_SOURCES
test/testprocmutex.c
test/testrand.c
test/testshm.c
test/testskiplist.c
test/testsleep.c
test/testsock.c
test/testsockets.c
@ -252,7 +253,6 @@ SET(APR_TEST_SOURCES
SET(install_targets)
SET(install_bin_pdb)
SET(install_lib_pdb)
# libapr-1 is shared, apr-1 is static
ADD_LIBRARY(libapr-1 SHARED ${APR_SOURCES} ${APR_PUBLIC_HEADERS_GENERATED} libapr.rc)
@ -264,7 +264,6 @@ ADD_DEPENDENCIES(libapr-1 test_char_header)
ADD_LIBRARY(apr-1 STATIC ${APR_SOURCES} ${APR_PUBLIC_HEADERS_GENERATED})
SET(install_targets ${install_targets} apr-1)
SET(install_lib_pdb ${install_lib_pdb} ${PROJECT_BINARY_DIR}/apr-1.pdb)
TARGET_LINK_LIBRARIES(apr-1 ${APR_SYSTEM_LIBS})
SET_TARGET_PROPERTIES(apr-1 PROPERTIES COMPILE_DEFINITIONS "APR_DECLARE_STATIC;WINNT")
ADD_DEPENDENCIES(apr-1 test_char_header)
@ -272,12 +271,10 @@ ADD_DEPENDENCIES(apr-1 test_char_header)
# libaprapp-1 and aprapp-1 are static
ADD_LIBRARY(libaprapp-1 STATIC misc/win32/apr_app.c misc/win32/internal.c ${APR_PUBLIC_HEADERS_GENERATED})
SET(install_targets ${install_targets} libaprapp-1)
SET(install_lib_pdb ${install_lib_pdb} ${PROJECT_BINARY_DIR}/libaprapp-1.pdb)
SET_TARGET_PROPERTIES(libaprapp-1 PROPERTIES COMPILE_DEFINITIONS "APR_APP;WINNT")
ADD_LIBRARY(aprapp-1 STATIC misc/win32/apr_app.c misc/win32/internal.c ${APR_PUBLIC_HEADERS_GENERATED})
SET(install_targets ${install_targets} aprapp-1)
SET(install_lib_pdb ${install_lib_pdb} ${PROJECT_BINARY_DIR}/aprapp-1.pdb)
SET_TARGET_PROPERTIES(aprapp-1 PROPERTIES COMPILE_DEFINITIONS "APR_DECLARE_STATIC;APR_APP;WINNT")
IF(APR_BUILD_TESTAPR)
@ -394,10 +391,6 @@ IF(INSTALL_PDB)
INSTALL(FILES ${install_bin_pdb}
DESTINATION bin
CONFIGURATIONS RelWithDebInfo Debug)
INSTALL(FILES ${install_lib_pdb}
DESTINATION lib
CONFIGURATIONS RelWithDebInfo Debug)
ENDIF()
INSTALL(FILES ${APR_PUBLIC_HEADERS_STATIC} ${APR_PUBLIC_HEADERS_GENERATED} DESTINATION include)

View File

@ -129,11 +129,11 @@ check: $(TARGET_LIB)
etags:
etags `find . -name '*.[ch]'`
make_tools_dir:
$(APR_MKDIR) tools
OBJECTS_gen_test_char = tools/gen_test_char.lo $(LOCAL_LIBS)
tools/gen_test_char.lo: make_tools_dir
tools/gen_test_char.lo: tools/gen_test_char.c
$(APR_MKDIR) tools
$(LT_COMPILE)
tools/gen_test_char@EXEEXT@: $(OBJECTS_gen_test_char)
$(LINK_PROG) $(OBJECTS_gen_test_char) $(ALL_LIBS)

View File

@ -1,5 +1,5 @@
Apache Portable Runtime
Copyright (c) 2000-2014 The Apache Software Foundation.
Copyright (c) 2000-2015 The Apache Software Foundation.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

View File

@ -50,6 +50,7 @@ include $(APR_WORK)/build/NWGNUhead.inc
#
XINCDIRS += \
$(APR)/include \
$(APR)/include/private \
$(APR)/include/arch/NetWare \
$(APR)/include/arch/unix \
$(APR)/memory/unix \
@ -293,11 +294,13 @@ FILES_nlm_exports = \
FILES_lib_objs = \
$(OBJDIR)/apr_atomic.o \
$(OBJDIR)/apr_cpystrn.o \
$(OBJDIR)/apr_escape.o \
$(OBJDIR)/apr_fnmatch.o \
$(OBJDIR)/apr_getpass.o \
$(OBJDIR)/apr_hash.o \
$(OBJDIR)/apr_pools.o \
$(OBJDIR)/apr_random.o \
$(OBJDIR)/apr_skiplist.o \
$(OBJDIR)/apr_snprintf.o \
$(OBJDIR)/apr_strings.o \
$(OBJDIR)/apr_strnatcmp.o \
@ -407,7 +410,7 @@ endif
vpath %.c atomic/netware:strings:tables:passwd:lib:time/unix
vpath %.c file_io/unix:locks/netware:misc/netware:misc/unix:threadproc/netware
vpath %.c poll/unix:shmem/unix:support/unix:random/unix
vpath %.c dso/netware:memory/unix:mmap/unix:user/netware
vpath %.c dso/netware:memory/unix:mmap/unix:user/netware:encoding
# Use the win32 network_io if Winsock is being used
ifndef USE_STDSOCKETS

View File

@ -907,69 +907,6 @@ SOURCE=.\include\apr_version.h
# Begin Source File
SOURCE=.\include\apr_want.h
!IF "$(CFG)" == "apr - Win32 Release"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\LibR\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "apr - Win32 Debug"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\LibD\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "apr - Win32 Release9x"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\9x\LibR\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "apr - Win32 Debug9x"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\9x\LibD\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "apr - x64 Release"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\x64\LibR\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "apr - x64 Debug"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\x64\LibD\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ENDIF
# End Source File
# End Group
# End Target

View File

@ -3,7 +3,7 @@
Summary: Apache Portable Runtime library
Name: apr
Version: 1.5.1
Version: 1.5.2
Release: 1
License: Apache Software License
Group: System Environment/Libraries
@ -76,7 +76,7 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root,-)
%doc docs/APRDesign.html docs/canonical_filenames.html
%doc docs/incomplete_types docs/non_apr_programs
%doc --parents html
%doc html
%{_bindir}/apr*config
%{_libdir}/libapr-%{aprver}.*a
%{_libdir}/libapr-%{aprver}.so

View File

@ -251,7 +251,7 @@ file_io/win32/filestat.lo: file_io/win32/filestat.c .make.dirs include/apr_alloc
file_io/win32/filesys.lo: file_io/win32/filesys.c .make.dirs include/apr_allocator.h include/apr_errno.h include/apr_general.h include/apr_pools.h include/apr_strings.h include/apr_thread_mutex.h include/apr_want.h
file_io/win32/flock.lo: file_io/win32/flock.c .make.dirs
file_io/win32/open.lo: file_io/win32/open.c .make.dirs include/apr_allocator.h include/apr_dso.h include/apr_errno.h include/apr_file_info.h include/apr_file_io.h include/apr_general.h include/apr_global_mutex.h include/apr_inherit.h include/apr_network_io.h include/apr_pools.h include/apr_portable.h include/apr_proc_mutex.h include/apr_shm.h include/apr_strings.h include/apr_tables.h include/apr_thread_mutex.h include/apr_thread_proc.h include/apr_time.h include/apr_user.h include/apr_want.h
file_io/win32/pipe.lo: file_io/win32/pipe.c .make.dirs include/apr_allocator.h include/apr_errno.h include/apr_file_info.h include/apr_file_io.h include/apr_general.h include/apr_inherit.h include/apr_pools.h include/apr_strings.h include/apr_tables.h include/apr_thread_mutex.h include/apr_time.h include/apr_user.h include/apr_want.h
file_io/win32/pipe.lo: file_io/win32/pipe.c .make.dirs include/apr_allocator.h include/apr_errno.h include/apr_escape.h include/apr_file_info.h include/apr_file_io.h include/apr_general.h include/apr_inherit.h include/apr_pools.h include/apr_strings.h include/apr_tables.h include/apr_thread_mutex.h include/apr_time.h include/apr_user.h include/apr_want.h
file_io/win32/readwrite.lo: file_io/win32/readwrite.c .make.dirs include/apr_allocator.h include/apr_errno.h include/apr_file_info.h include/apr_file_io.h include/apr_general.h include/apr_inherit.h include/apr_lib.h include/apr_pools.h include/apr_strings.h include/apr_tables.h include/apr_thread_mutex.h include/apr_time.h include/apr_user.h include/apr_want.h
file_io/win32/seek.lo: file_io/win32/seek.c .make.dirs include/apr_allocator.h include/apr_errno.h include/apr_file_info.h include/apr_file_io.h include/apr_general.h include/apr_inherit.h include/apr_pools.h include/apr_tables.h include/apr_thread_mutex.h include/apr_time.h include/apr_user.h include/apr_want.h

73
contrib/apr/configure vendored
View File

@ -6802,10 +6802,10 @@ if test "x$apr_preload_done" != "xyes" ; then
*-apple-darwin*)
if test "x$CPPFLAGS" = "x"; then
test "x$silent" != "xyes" && echo " setting CPPFLAGS to \"-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp\""
CPPFLAGS="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp"
test "x$silent" != "xyes" && echo " setting CPPFLAGS to \"-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK\""
CPPFLAGS="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"
else
apr_addto_bugger="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp"
apr_addto_bugger="-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK"
for i in $apr_addto_bugger; do
apr_addto_duplicate="0"
for j in $CPPFLAGS; do
@ -18794,7 +18794,34 @@ if test "${enable_nonportable_atomics+set}" = set; then :
else
case $host_cpu in
i[456]86) force_generic_atomics=yes ;;
*) force_generic_atomics=no ;;
*) force_generic_atomics=no
case $host in
*solaris2.10*)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <atomic.h>
int
main ()
{
void *ptr = NULL; atomic_cas_ptr(&ptr, NULL, NULL);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
else
force_generic_atomics=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $force_generic_atomics = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: nonportable atomic support disabled, system needs Patch-ID 118884 or 118885" >&5
$as_echo "$as_me: nonportable atomic support disabled, system needs Patch-ID 118884 or 118885" >&6;}
fi
;;
esac
;;
esac
fi
@ -22292,7 +22319,7 @@ else
fi
done
for ac_func in getpass getpassphrase gmtime_r localtime_r mkstemp
for ac_func in getpass getpassphrase gmtime_r localtime_r
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -22304,6 +22331,23 @@ _ACEOF
fi
done
case $host in
*-hp-hpux*)
;;
*)
for ac_func in mkstemp
do :
ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
if test "x$ac_cv_func_mkstemp" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_MKSTEMP 1
_ACEOF
fi
done
;;
esac
@ -23902,7 +23946,7 @@ _ACEOF
if test "${ac_cv_sizeof_off_t}${apr_cv_use_lfs64}" = "4yes"; then
# Enable LFS
aprlfs=1
for ac_func in mmap64 sendfile64 sendfilev64 mkstemp64 readdir64_r
for ac_func in mmap64 sendfile64 sendfilev64 readdir64_r
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -23914,6 +23958,23 @@ _ACEOF
fi
done
case $host in
*-hp-hpux*)
;;
*)
for ac_func in mkstemp64
do :
ac_fn_c_check_func "$LINENO" "mkstemp64" "ac_cv_func_mkstemp64"
if test "x$ac_cv_func_mkstemp64" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_MKSTEMP64 1
_ACEOF
fi
done
;;
esac
elif test "${ac_cv_sizeof_off_t}" != "${ac_cv_sizeof_size_t}"; then
# unsure of using -gt above is as portable, can can't forsee where
# off_t can legitimately be smaller than size_t

View File

@ -640,7 +640,20 @@ AC_ARG_ENABLE(nonportable-atomics,
],
[case $host_cpu in
i[[456]]86) force_generic_atomics=yes ;;
*) force_generic_atomics=no ;;
*) force_generic_atomics=no
case $host in
*solaris2.10*)
AC_TRY_COMPILE(
[#include <atomic.h>],
[void *ptr = NULL; atomic_cas_ptr(&ptr, NULL, NULL);],,
[force_generic_atomics=yes]
)
if test $force_generic_atomics = yes; then
AC_MSG_NOTICE([nonportable atomic support disabled, system needs Patch-ID 118884 or 118885])
fi
;;
esac
;;
esac
])
@ -1400,7 +1413,15 @@ if test "$native_mmap_emul" = "1"; then
mmap="1"
fi
AC_CHECK_FUNCS(memmove, [ have_memmove="1" ], [have_memmove="0" ])
AC_CHECK_FUNCS([getpass getpassphrase gmtime_r localtime_r mkstemp])
AC_CHECK_FUNCS([getpass getpassphrase gmtime_r localtime_r])
case $host in
*-hp-hpux*)
dnl mkstemp is limited to 26 temporary files (a-z); use APR replacement
;;
*)
AC_CHECK_FUNCS(mkstemp)
;;
esac
AC_SUBST(fork)
AC_SUBST(have_inet_addr)
@ -1801,7 +1822,15 @@ APR_CHECK_SIZEOF_EXTENDED([#include <sys/types.h>], off_t, 8)
if test "${ac_cv_sizeof_off_t}${apr_cv_use_lfs64}" = "4yes"; then
# Enable LFS
aprlfs=1
AC_CHECK_FUNCS([mmap64 sendfile64 sendfilev64 mkstemp64 readdir64_r])
AC_CHECK_FUNCS([mmap64 sendfile64 sendfilev64 readdir64_r])
case $host in
*-hp-hpux*)
dnl mkstemp64 is limited to 26 temporary files (a-z); use APR replacement
;;
*)
AC_CHECK_FUNCS(mkstemp64)
;;
esac
elif test "${ac_cv_sizeof_off_t}" != "${ac_cv_sizeof_size_t}"; then
# unsure of using -gt above is as portable, can can't forsee where
# off_t can legitimately be smaller than size_t

View File

@ -436,6 +436,8 @@ APR_DECLARE(apr_status_t) apr_escape_path(char *escaped, const char *path,
while ((c = *s) && slen) {
if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
d = c2x(c, '%', d);
size += 2;
found = 1;
}
else {
*d++ = c;

View File

@ -40,7 +40,9 @@ extern "C" {
/**
* apr_skiplist_compare is the function type that must be implemented
* per object type that is used in a skip list for comparisons to maintain
* order
* order. A value <0 indicates placement after this node; a value of 0
* indicates collision with this exact node; a value >0 indicates placement
* before this node.
* */
typedef int (*apr_skiplist_compare) (void *, void *);
@ -171,7 +173,8 @@ APR_DECLARE(void *) apr_skiplist_next(apr_skiplist *sl, apr_skiplistnode **iter)
APR_DECLARE(void *) apr_skiplist_previous(apr_skiplist *sl, apr_skiplistnode **iter);
/**
* Insert an element into the skip list using the specified comparison function.
* Insert an element into the skip list using the specified comparison function
* if it does not already exist.
* @param sl The skip list
* @param data The element to insert
* @param comp The comparison function to use for placement into the skip list
@ -180,7 +183,8 @@ APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl,
void *data, apr_skiplist_compare comp);
/**
* Insert an element into the skip list using the existing comparison function.
* Insert an element into the skip list using the existing comparison function
* if it does not already exist (as determined by the comparison function)
* @param sl The skip list
* @param data The element to insert
* @remark If no comparison function has been set for the skip list, the element
@ -190,7 +194,7 @@ APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist* sl, void *data
/**
* Remove an element from the skip list using the specified comparison function for
* locating the element.
* locating the element. In the case of duplicates, the 1st entry will be removed.
* @param sl The skip list
* @param data The element to remove
* @param myfree A function to be called for each removed element
@ -203,7 +207,7 @@ APR_DECLARE(int) apr_skiplist_remove_compare(apr_skiplist *sl, void *data,
/**
* Remove an element from the skip list using the existing comparison function for
* locating the element.
* locating the element. In the case of duplicates, the 1st entry will be removed.
* @param sl The skip list
* @param data The element to remove
* @param myfree A function to be called for each removed element
@ -229,7 +233,7 @@ APR_DECLARE(void) apr_skiplist_remove_all(apr_skiplist *sl, apr_skiplist_freefun
APR_DECLARE(void) apr_skiplist_destroy(apr_skiplist *sl, apr_skiplist_freefunc myfree);
/**
* Return the first element in the skip list, leaving the element in the skip list.
* Return the first element in the skip list, removing the element from the skip list.
* @param sl The skip list
* @param myfree A function to be called for the removed element
* @remark NULL will be returned if there are no elements

View File

@ -38,7 +38,7 @@
*/
#define APR_COPYRIGHT "Copyright (c) 2000-2014 The Apache Software " \
#define APR_COPYRIGHT "Copyright (c) 2000-2015 The Apache Software " \
"Foundation or its licensors, as applicable."
/* The numeric compile-time version constants. These constants are the
@ -62,7 +62,7 @@
* The Patch Level never includes API changes, simply bug fixes.
* Reset to 0 when upgrading APR_MINOR_VERSION
*/
#define APR_PATCH_VERSION 1
#define APR_PATCH_VERSION 2
/**
* The symbol APR_IS_DEV_VERSION is only defined for internal,

View File

@ -765,7 +765,7 @@ SOURCE=.\include\apr_escape.h
# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
InputPath=.\include\apr_escape.h
".\Release\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\Release\gen_test_char /Fe.\Release\gen_test_char.exe .\tools\gen_test_char.c
.\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
@ -776,7 +776,7 @@ InputPath=.\include\apr_escape.h
# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
InputPath=.\include\apr_escape.h
".\Debug\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\Debug\gen_test_char /Fe.\Debug\gen_test_char.exe .\tools\gen_test_char.c
.\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
@ -787,7 +787,7 @@ InputPath=.\include\apr_escape.h
# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
InputPath=.\include\apr_escape.h
".\9x\Release\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\9x\Release\gen_test_char /Fe.\9x\Release\gen_test_char.exe .\tools\gen_test_char.c
.\9x\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
@ -798,7 +798,7 @@ InputPath=.\include\apr_escape.h
# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
InputPath=.\include\apr_escape.h
".\9x\Debug\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\9x\Debug\gen_test_char /Fe.\9x\Debug\gen_test_char.exe .\tools\gen_test_char.c
.\9x\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
@ -809,7 +809,7 @@ InputPath=.\include\apr_escape.h
# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
InputPath=.\include\apr_escape.h
".\x64\Release\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl.exe /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\x64\Release\gen_test_char /Fe.\x64\Release\gen_test_char.exe .\tools\gen_test_char.c
.\x64\Release\gen_test_char.exe > .\include\apr_escape_test_char.h
@ -820,7 +820,7 @@ InputPath=.\include\apr_escape.h
# Begin Custom Build - Creating gen_test_char.exe and apr_escape_test_char.h
InputPath=.\include\apr_escape.h
".\x64\Debug\gen_test_char.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
cl.exe /nologo /W3 /EHsc /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /I ".\include" /Fo.\x64\Debug\gen_test_char /Fe.\x64\Debug\gen_test_char.exe .\tools\gen_test_char.c
.\x64\Debug\gen_test_char.exe > .\include\apr_escape_test_char.h
@ -952,69 +952,6 @@ SOURCE=.\include\apr_version.h
# Begin Source File
SOURCE=.\include\apr_want.h
!IF "$(CFG)" == "libapr - Win32 Release"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "libapr - Win32 Debug"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "libapr - Win32 Release9x"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "libapr - Win32 Debug9x"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "libapr - x64 Release"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ELSEIF "$(CFG)" == "libapr - x64 Debug"
# Begin Custom Build
InputPath=.\include\apr_want.h
".\include\apr_escape_test_char.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
type .\include\apr.hw > .\include\apr.h
# End Custom Build
!ENDIF
# End Source File
# End Group
# Begin Source File

View File

@ -114,7 +114,9 @@ static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex,
usec = apr_time_usec(now);
apr_snprintf(semname, sizeof(semname), "/ApR.%lxZ%lx", sec, usec);
}
psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
do {
psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
} while (psem == (sem_t *)SEM_FAILED && errno == EINTR);
if (psem == (sem_t *)SEM_FAILED) {
if (errno == ENAMETOOLONG) {
/* Oh well, good try */
@ -122,7 +124,9 @@ static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex,
} else {
return errno;
}
psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
do {
psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
} while (psem == (sem_t *)SEM_FAILED && errno == EINTR);
}
if (psem == (sem_t *)SEM_FAILED) {
@ -140,7 +144,12 @@ static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex,
static apr_status_t proc_mutex_posix_acquire(apr_proc_mutex_t *mutex)
{
if (sem_wait(mutex->psem_interproc) < 0) {
int rc;
do {
rc = sem_wait(mutex->psem_interproc);
} while (rc < 0 && errno == EINTR);
if (rc < 0) {
return errno;
}
mutex->curr_locked = 1;
@ -149,7 +158,12 @@ static apr_status_t proc_mutex_posix_acquire(apr_proc_mutex_t *mutex)
static apr_status_t proc_mutex_posix_tryacquire(apr_proc_mutex_t *mutex)
{
if (sem_trywait(mutex->psem_interproc) < 0) {
int rc;
do {
rc = sem_trywait(mutex->psem_interproc);
} while (rc < 0 && errno == EINTR);
if (rc < 0) {
if (errno == EAGAIN) {
return APR_EBUSY;
}

View File

@ -1135,21 +1135,12 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap)
* room to hold the NUL terminator.
*/
if (ps.node->first_avail == ps.node->endp) {
if (psprintf_flush(&ps.vbuff) == -1) {
if (pool->abort_fn) {
pool->abort_fn(APR_ENOMEM);
}
return NULL;
}
if (psprintf_flush(&ps.vbuff) == -1)
goto error;
}
if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) {
if (pool->abort_fn)
pool->abort_fn(APR_ENOMEM);
return NULL;
}
if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1)
goto error;
strp = ps.vbuff.curpos;
*strp++ = '\0';
@ -1195,6 +1186,15 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap)
list_insert(active, node);
return strp;
error:
if (pool->abort_fn)
pool->abort_fn(APR_ENOMEM);
if (ps.got_a_new_node) {
ps.node->next = ps.free;
allocator_free(pool->allocator, ps.node);
}
return NULL;
}

View File

@ -39,6 +39,8 @@ static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s)
static char *apr_error_string(apr_status_t statcode)
{
switch (statcode) {
case APR_ENOSTAT:
return "Could not perform a stat on the file.";
case APR_ENOPOOL:
return "A new pool could not be created.";
case APR_EBADDATE:
@ -73,7 +75,10 @@ static char *apr_error_string(apr_status_t statcode)
return "The specified IP address is invalid.";
case APR_EBADMASK:
return "The specified network mask is invalid.";
case APR_ESYMNOTFOUND:
return "Could not find the requested symbol.";
case APR_ENOTENOUGHENTROPY:
return "Not enough entropy to continue.";
case APR_INCHILD:
return
"Your code just forked, and you are currently executing in the "
@ -128,10 +133,12 @@ static char *apr_error_string(apr_status_t statcode)
return "The given path is misformatted or contained invalid characters";
case APR_EPATHWILD:
return "The given path contained wildcard characters";
case APR_EBUSY:
return "The given lock was busy.";
case APR_EPROC_UNKNOWN:
return "The process is not recognized.";
case APR_EGENERAL:
return "Internal error";
return "Internal error (specific information not available)";
default:
return "Error string not specified yet";
}

View File

@ -325,6 +325,16 @@ static apr_status_t call_resolver(apr_sockaddr_t **sa,
hints.ai_flags = AI_ADDRCONFIG;
}
#endif
#ifdef __MVS__
/* z/OS will not return IPv4 address under AF_UNSPEC if any IPv6 results
* are returned, w/o AI_ALL.
*/
if (family == APR_UNSPEC) {
hints.ai_flags |= AI_ALL;
}
#endif
if(hostname == NULL) {
#ifdef AI_PASSIVE
/* If hostname is NULL, assume we are trying to bind to all

View File

@ -145,13 +145,22 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
#ifndef HAVE_SOCK_CLOEXEC
{
int flags;
apr_status_t rv;
if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1)
return errno;
if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) {
rv = errno;
close((*new)->socketdes);
(*new)->socketdes = -1;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl((*new)->socketdes, F_SETFD, flags) == -1)
return errno;
if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) {
rv = errno;
close((*new)->socketdes);
(*new)->socketdes = -1;
return rv;
}
}
#endif
@ -306,13 +315,22 @@ apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock,
#ifndef HAVE_ACCEPT4
{
int flags;
apr_status_t rv;
if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1)
return errno;
if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) {
rv = errno;
close((*new)->socketdes);
(*new)->socketdes = -1;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl((*new)->socketdes, F_SETFD, flags) == -1)
return errno;
if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) {
rv = errno;
close((*new)->socketdes);
(*new)->socketdes = -1;
return rv;
}
}
#endif

View File

@ -104,14 +104,22 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
#ifndef HAVE_EPOLL_CREATE1
{
int flags;
int fd_flags;
if ((flags = fcntl(fd, F_GETFD)) == -1)
return errno;
if ((fd_flags = fcntl(fd, F_GETFD)) == -1) {
rv = errno;
close(fd);
pollset->p = NULL;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1)
return errno;
fd_flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, fd_flags) == -1) {
rv = errno;
close(fd);
pollset->p = NULL;
return rv;
}
}
#endif
@ -122,11 +130,13 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
APR_THREAD_MUTEX_DEFAULT,
p)) != APR_SUCCESS)) {
close(fd);
pollset->p = NULL;
return rv;
}
#else
if (flags & APR_POLLSET_THREADSAFE) {
close(fd);
pollset->p = NULL;
return APR_ENOTIMPL;
}
@ -345,14 +355,23 @@ static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
#ifndef HAVE_EPOLL_CREATE1
{
int flags;
int fd_flags;
apr_status_t rv;
if ((flags = fcntl(fd, F_GETFD)) == -1)
return errno;
if ((fd_flags = fcntl(fd, F_GETFD)) == -1) {
rv = errno;
close(fd);
pollcb->fd = -1;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1)
return errno;
fd_flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, fd_flags) == -1) {
rv = errno;
close(fd);
pollcb->fd = -1;
return rv;
}
}
#endif

View File

@ -115,12 +115,20 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
{
int flags;
if ((flags = fcntl(pollset->p->kqueue_fd, F_GETFD)) == -1)
return errno;
if ((flags = fcntl(pollset->p->kqueue_fd, F_GETFD)) == -1) {
rv = errno;
close(pollset->p->kqueue_fd);
pollset->p = NULL;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl(pollset->p->kqueue_fd, F_SETFD, flags) == -1)
return errno;
if (fcntl(pollset->p->kqueue_fd, F_SETFD, flags) == -1) {
rv = errno;
close(pollset->p->kqueue_fd);
pollset->p = NULL;
return rv;
}
}
pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t));
@ -338,13 +346,22 @@ static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
{
int flags;
apr_status_t rv;
if ((flags = fcntl(fd, F_GETFD)) == -1)
return errno;
if ((flags = fcntl(fd, F_GETFD)) == -1) {
rv = errno;
close(fd);
pollcb->fd = -1;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1)
return errno;
if (fcntl(fd, F_SETFD, flags) == -1) {
rv = errno;
close(fd);
pollcb->fd = -1;
return rv;
}
}
pollcb->fd = fd;

View File

@ -240,26 +240,25 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
{
int ret;
apr_status_t rv = APR_SUCCESS;
#ifdef WIN32
apr_interval_time_t orig_timeout = timeout;
#endif
if (timeout > 0) {
timeout /= 1000;
}
#ifdef WIN32
/* WSAPoll() requires at least one socket. */
if (pollset->nelts == 0) {
*num = 0;
if (orig_timeout > 0) {
apr_sleep(orig_timeout);
if (timeout > 0) {
apr_sleep(timeout);
return APR_TIMEUP;
}
return APR_SUCCESS;
}
if (timeout > 0) {
timeout /= 1000;
}
ret = WSAPoll(pollset->p->pollset, pollset->nelts, (int)timeout);
#else
if (timeout > 0) {
timeout /= 1000;
}
ret = poll(pollset->p->pollset, pollset->nelts, timeout);
#endif
(*num) = ret;
@ -398,12 +397,23 @@ static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
apr_status_t rv = APR_SUCCESS;
apr_uint32_t i;
#ifdef WIN32
/* WSAPoll() requires at least one socket. */
if (pollcb->nelts == 0) {
if (timeout > 0) {
apr_sleep(timeout);
return APR_TIMEUP;
}
return APR_SUCCESS;
}
if (timeout > 0) {
timeout /= 1000;
}
#ifdef WIN32
ret = WSAPoll(pollcb->pollset.ps, pollcb->nelts, (int)timeout);
#else
if (timeout > 0) {
timeout /= 1000;
}
ret = poll(pollcb->pollset.ps, pollcb->nelts, timeout);
#endif
if (ret < 0) {

View File

@ -136,6 +136,9 @@ APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb,
}
pollcb->provider = provider;
}
else if (rv != APR_SUCCESS) {
return rv;
}
*ret_pollcb = pollcb;
return APR_SUCCESS;

View File

@ -188,12 +188,20 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
{
int flags;
if ((flags = fcntl(pollset->p->port_fd, F_GETFD)) == -1)
return errno;
if ((flags = fcntl(pollset->p->port_fd, F_GETFD)) == -1) {
rv = errno;
close(pollset->p->port_fd);
pollset->p = NULL;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl(pollset->p->port_fd, F_SETFD, flags) == -1)
return errno;
if (fcntl(pollset->p->port_fd, F_SETFD, flags) == -1) {
rv = errno;
close(pollset->p->port_fd);
pollset->p = NULL;
return rv;
}
}
pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
@ -478,13 +486,22 @@ static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
{
int flags;
apr_status_t rv;
if ((flags = fcntl(pollcb->fd, F_GETFD)) == -1)
return errno;
if ((flags = fcntl(pollcb->fd, F_GETFD)) == -1) {
rv = errno;
close(pollcb->fd);
pollcb->fd = -1;
return rv;
}
flags |= FD_CLOEXEC;
if (fcntl(pollcb->fd, F_SETFD, flags) == -1)
return errno;
if (fcntl(pollcb->fd, F_SETFD, flags) == -1) {
rv = errno;
close(pollcb->fd);
pollcb->fd = -1;
return rv;
}
}
pollcb->pollset.port = apr_palloc(p, size * sizeof(port_event_t));

View File

@ -272,7 +272,7 @@ static apr_status_t asio_pollset_create(apr_pollset_t *pollset,
APR_THREAD_MUTEX_DEFAULT,
p) != APR_SUCCESS) {
DBG1(1, "apr_thread_mutex_create returned %d\n", rv);
pollset = NULL;
pollset->p = NULL;
return rv;
}
rv = msgget(IPC_PRIVATE, S_IWUSR+S_IRUSR); /* user r/w perms */
@ -280,7 +280,7 @@ static apr_status_t asio_pollset_create(apr_pollset_t *pollset,
#if DEBUG
perror(__FUNCTION__ " msgget returned < 0 ");
#endif
pollset = NULL;
pollset->p = NULL;
return rv;
}
@ -292,7 +292,7 @@ static apr_status_t asio_pollset_create(apr_pollset_t *pollset,
APR_RING_INIT(&priv->prior_ready_ring, asio_elem_t, link);
#else /* APR doesn't have threads but caller wants a threadsafe pollset */
pollset = NULL;
pollset->p = NULL;
return APR_ENOTIMPL;
#endif
@ -304,6 +304,7 @@ static apr_status_t asio_pollset_create(apr_pollset_t *pollset,
priv->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
if ((!priv->pollset) || (!priv->query_set)) {
pollset->p = NULL;
return APR_ENOMEM;
}
}
@ -314,6 +315,10 @@ static apr_status_t asio_pollset_create(apr_pollset_t *pollset,
priv->size = size;
priv->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
if (!priv->result_set) {
if (flags & APR_POLLSET_THREADSAFE) {
msgctl(priv->msg_q, IPC_RMID, NULL);
}
pollset->p = NULL;
return APR_ENOMEM;
}
@ -379,6 +384,7 @@ static apr_status_t asio_pollset_add(apr_pollset_t *pollset,
APR_RING_REMOVE(elem, link);
DBG1(3, "used recycled memory at %08p\n", elem);
elem->state = ASIO_INIT;
elem->a.aio_cflags = 0;
}
else {
elem = (asio_elem_t *) apr_pcalloc(pollset->pool, sizeof(asio_elem_t));
@ -659,6 +665,7 @@ static apr_status_t asio_pollset_poll(apr_pollset_t *pollset,
if (ret == 1) {
DBG(4, "asyncio() completed inline\n");
/* it's ready now */
elem->state = ASIO_COMPLETE;
APR_RING_INSERT_TAIL(&(priv->ready_ring), elem, asio_elem_t,
link);
}

View File

@ -25,12 +25,18 @@
#include "apr_skiplist.h"
typedef struct {
apr_skiplistnode **data;
size_t size, pos;
apr_pool_t *p;
} apr_skiplist_q;
struct apr_skiplist {
apr_skiplist_compare compare;
apr_skiplist_compare comparek;
int height;
int preheight;
int size;
size_t size;
apr_skiplistnode *top;
apr_skiplistnode *bottom;
/* These two are needed for appending */
@ -38,6 +44,8 @@ struct apr_skiplist {
apr_skiplistnode *bottomend;
apr_skiplist *index;
apr_array_header_t *memlist;
apr_skiplist_q nodes_q,
stack_q;
apr_pool_t *pool;
};
@ -52,20 +60,15 @@ struct apr_skiplistnode {
apr_skiplist *sl;
};
#ifndef MIN
#define MIN(a,b) ((a<b)?(a):(b))
#endif
static int get_b_rand(void)
{
static int ph = 32; /* More bits than we will ever use */
static apr_uint32_t randseq;
static int randseq;
if (ph > 31) { /* Num bits in return of rand() */
ph = 0;
randseq = (apr_uint32_t) rand();
randseq = rand();
}
ph++;
return ((randseq & (1 << (ph - 1))) >> (ph - 1));
return randseq & (1 << ph++);
}
typedef struct {
@ -103,7 +106,7 @@ APR_DECLARE(void *) apr_skiplist_alloc(apr_skiplist *sl, size_t size)
memlist++;
}
/* no free chunks */
ptr = apr_pcalloc(sl->pool, size);
ptr = apr_palloc(sl->pool, size);
if (!ptr) {
return ptr;
}
@ -122,7 +125,7 @@ APR_DECLARE(void *) apr_skiplist_alloc(apr_skiplist *sl, size_t size)
return ptr;
}
else {
return calloc(1, size);
return malloc(size);
}
}
@ -149,27 +152,73 @@ APR_DECLARE(void) apr_skiplist_free(apr_skiplist *sl, void *mem)
}
}
static apr_status_t skiplist_qpush(apr_skiplist_q *q, apr_skiplistnode *m)
{
if (q->pos >= q->size) {
apr_skiplistnode **data;
size_t size = (q->pos) ? q->pos * 2 : 32;
if (q->p) {
data = apr_palloc(q->p, size * sizeof(*data));
if (data) {
memcpy(data, q->data, q->pos * sizeof(*data));
}
}
else {
data = realloc(q->data, size * sizeof(*data));
}
if (!data) {
return APR_ENOMEM;
}
q->data = data;
q->size = size;
}
q->data[q->pos++] = m;
return APR_SUCCESS;
}
static APR_INLINE apr_skiplistnode *skiplist_qpop(apr_skiplist_q *q)
{
return (q->pos > 0) ? q->data[--q->pos] : NULL;
}
static APR_INLINE void skiplist_qclear(apr_skiplist_q *q)
{
q->pos = 0;
}
static apr_skiplistnode *skiplist_new_node(apr_skiplist *sl)
{
apr_skiplistnode *m = skiplist_qpop(&sl->nodes_q);
if (!m) {
if (sl->pool) {
m = apr_palloc(sl->pool, sizeof *m);
}
else {
m = malloc(sizeof *m);
}
}
return m;
}
static apr_status_t skiplist_free_node(apr_skiplist *sl, apr_skiplistnode *m)
{
return skiplist_qpush(&sl->nodes_q, m);
}
static apr_status_t skiplisti_init(apr_skiplist **s, apr_pool_t *p)
{
apr_skiplist *sl;
if (p) {
sl = apr_pcalloc(p, sizeof(apr_skiplist));
sl->memlist = apr_array_make(p, 20, sizeof(memlist_t));
sl->pool = sl->nodes_q.p = sl->stack_q.p = p;
}
else {
sl = calloc(1, sizeof(apr_skiplist));
if (!sl) {
return APR_ENOMEM;
}
}
#if 0
sl->compare = (apr_skiplist_compare) NULL;
sl->comparek = (apr_skiplist_compare) NULL;
sl->height = 0;
sl->preheight = 0;
sl->size = 0;
sl->top = NULL;
sl->bottom = NULL;
sl->index = NULL;
#endif
sl->pool = p;
*s = sl;
return APR_SUCCESS;
}
@ -248,56 +297,32 @@ APR_DECLARE(void) apr_skiplist_add_index(apr_skiplist *sl,
}
}
APR_DECLARE(apr_skiplistnode *) apr_skiplist_getlist(apr_skiplist *sl)
{
if (!sl->bottom) {
return NULL;
}
return sl->bottom->next;
}
APR_DECLARE(void *) apr_skiplist_find(apr_skiplist *sl, void *data, apr_skiplistnode **iter)
{
void *ret;
apr_skiplistnode *aiter;
if (!sl->compare) {
return 0;
}
if (iter) {
ret = apr_skiplist_find_compare(sl, data, iter, sl->compare);
}
else {
ret = apr_skiplist_find_compare(sl, data, &aiter, sl->compare);
}
return ret;
}
static int skiplisti_find_compare(apr_skiplist *sl, void *data,
apr_skiplistnode **ret,
apr_skiplist_compare comp)
{
apr_skiplistnode *m = NULL;
int count = 0;
apr_skiplistnode *m;
m = sl->top;
while (m) {
int compared;
compared = (m->next) ? comp(data, m->next->data) : -1;
if (compared == 0) {
m = m->next;
while (m->down) {
m = m->down;
if (m->next) {
int compared = comp(data, m->next->data);
if (compared == 0) {
m = m->next;
while (m->down) {
m = m->down;
}
*ret = m;
return count;
}
if (compared > 0) {
m = m->next;
count++;
continue;
}
*ret = m;
return count;
}
if ((m->next == NULL) || (compared < 0)) {
m = m->down;
count++;
}
else {
m = m->next;
count++;
}
m = m->down;
count++;
}
*ret = NULL;
return count;
@ -307,19 +332,47 @@ APR_DECLARE(void *) apr_skiplist_find_compare(apr_skiplist *sli, void *data,
apr_skiplistnode **iter,
apr_skiplist_compare comp)
{
apr_skiplistnode *m = NULL;
apr_skiplistnode *m;
apr_skiplist *sl;
if (!comp) {
if (iter) {
*iter = NULL;
}
return NULL;
}
if (comp == sli->compare || !sli->index) {
sl = sli;
}
else {
apr_skiplist_find(sli->index, (void *)comp, &m);
if (!m) {
if (iter) {
*iter = NULL;
}
return NULL;
}
sl = (apr_skiplist *) m->data;
}
skiplisti_find_compare(sl, data, iter, sl->comparek);
return (iter && *iter) ? ((*iter)->data) : NULL;
skiplisti_find_compare(sl, data, &m, sl->comparek);
if (iter) {
*iter = m;
}
return (m) ? m->data : NULL;
}
APR_DECLARE(void *) apr_skiplist_find(apr_skiplist *sl, void *data, apr_skiplistnode **iter)
{
return apr_skiplist_find_compare(sl, data, iter, sl->compare);
}
APR_DECLARE(apr_skiplistnode *) apr_skiplist_getlist(apr_skiplist *sl)
{
if (!sl->bottom) {
return NULL;
}
return sl->bottom->next;
}
APR_DECLARE(void *) apr_skiplist_next(apr_skiplist *sl, apr_skiplistnode **iter)
{
@ -339,98 +392,74 @@ APR_DECLARE(void *) apr_skiplist_previous(apr_skiplist *sl, apr_skiplistnode **i
return (*iter) ? ((*iter)->data) : NULL;
}
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist *sl, void *data)
static APR_INLINE int skiplist_height(const apr_skiplist *sl)
{
if (!sl->compare) {
return 0;
}
return apr_skiplist_insert_compare(sl, data, sl->compare);
/* Skiplists (even empty) always have a top node, although this
* implementation defers its creation until the first insert, or
* deletes it with the last remove. We want the real height here.
*/
return sl->height ? sl->height : 1;
}
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl, void *data,
apr_skiplist_compare comp)
{
apr_skiplistnode *m, *p, *tmp, *ret = NULL, **stack;
int nh = 1, ch, stacki;
if (!sl->top) {
sl->height = 1;
sl->topend = sl->bottomend = sl->top = sl->bottom =
(apr_skiplistnode *)apr_skiplist_alloc(sl, sizeof(apr_skiplistnode));
#if 0
sl->top->next = (apr_skiplistnode *)NULL;
sl->top->data = (apr_skiplistnode *)NULL;
sl->top->prev = (apr_skiplistnode *)NULL;
sl->top->up = (apr_skiplistnode *)NULL;
sl->top->down = (apr_skiplistnode *)NULL;
sl->top->nextindex = (apr_skiplistnode *)NULL;
sl->top->previndex = (apr_skiplistnode *)NULL;
#endif
sl->top->sl = sl;
apr_skiplistnode *m, *p, *tmp, *ret = NULL;
int ch, nh = 1;
if (!comp) {
return NULL;
}
ch = skiplist_height(sl);
if (sl->preheight) {
while (nh < sl->preheight && get_b_rand()) {
nh++;
}
}
else {
while (nh <= sl->height && get_b_rand()) {
while (nh <= ch && get_b_rand()) {
nh++;
}
}
/* Now we have the new height at which we wish to insert our new node */
/*
* Let us make sure that our tree is a least that tall (grow if
* necessary)
/* Now we have in nh the height at which we wish to insert our new node,
* and in ch the current height: don't create skip paths to the inserted
* element until the walk down through the tree (which decrements ch)
* reaches nh. From there, any walk down pushes the current node on a
* stack (the node(s) after which we would insert) to pop back through
* for insertion later.
*/
for (; sl->height < nh; sl->height++) {
sl->top->up =
(apr_skiplistnode *)apr_skiplist_alloc(sl, sizeof(apr_skiplistnode));
sl->top->up->down = sl->top;
sl->top = sl->topend = sl->top->up;
#if 0
sl->top->prev = sl->top->next = sl->top->nextindex =
sl->top->previndex = sl->top->up = NULL;
sl->top->data = NULL;
#endif
sl->top->sl = sl;
}
ch = sl->height;
/* Find the node (or node after which we would insert) */
/* Keep a stack to pop back through for insertion */
/* malloc() is OK since we free the temp stack */
m = sl->top;
stack = (apr_skiplistnode **)malloc(sizeof(apr_skiplistnode *) * (nh));
stacki = 0;
while (m) {
int compared = -1;
if (m->next) {
compared = comp(data, m->next->data);
}
if (compared == 0) {
free(stack); /* OK. was malloc'ed */
return 0;
}
if ((m->next == NULL) || (compared < 0)) {
if (ch <= nh) {
/* push on stack */
stack[stacki++] = m;
int compared = comp(data, m->next->data);
if (compared == 0) {
/* Keep the existing element(s) */
skiplist_qclear(&sl->stack_q);
return NULL;
}
if (compared > 0) {
m = m->next;
continue;
}
m = m->down;
ch--;
}
else {
m = m->next;
if (ch <= nh) {
/* push on stack */
skiplist_qpush(&sl->stack_q, m);
}
m = m->down;
ch--;
}
/* Pop the stack and insert nodes */
p = NULL;
for (; stacki > 0; stacki--) {
m = stack[stacki - 1];
tmp = (apr_skiplistnode *)apr_skiplist_alloc(sl, sizeof(apr_skiplistnode));
while ((m = skiplist_qpop(&sl->stack_q))) {
tmp = skiplist_new_node(sl);
tmp->next = m->next;
if (m->next) {
m->next->prev = tmp;
}
m->next = tmp;
tmp->prev = m;
tmp->up = NULL;
tmp->nextindex = tmp->previndex = NULL;
@ -438,17 +467,44 @@ APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl, vo
if (p) {
p->up = tmp;
}
else {
/* This sets ret to the bottom-most node we are inserting */
ret = tmp;
}
tmp->data = data;
tmp->sl = sl;
p = tmp;
}
/* Now we are sure the node is inserted, grow our tree to 'nh' tall */
for (; sl->height < nh; sl->height++) {
m = skiplist_new_node(sl);
tmp = skiplist_new_node(sl);
m->up = m->prev = m->nextindex = m->previndex = NULL;
m->next = tmp;
/* This sets ret to the bottom-most node we are inserting */
if (!p) {
m->down = sl->top;
m->data = NULL;
m->sl = sl;
if (sl->top) {
sl->top->up = m;
}
else {
sl->bottom = sl->bottomend = m;
}
sl->top = sl->topend = tmp->prev = m;
tmp->up = tmp->next = tmp->nextindex = tmp->previndex = NULL;
tmp->down = p;
tmp->data = data;
tmp->sl = sl;
if (p) {
p->up = tmp;
}
else {
/* This sets ret to the bottom-most node we are inserting */
ret = tmp;
sl->size++; /* this seems to go here got each element to be counted */
}
p = tmp;
}
free(stack); /* OK. was malloc'ed */
if (sl->index != NULL) {
/*
* this is a external insertion, we must insert into each index as
@ -457,25 +513,20 @@ APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl, vo
apr_skiplistnode *ni, *li;
li = ret;
for (p = apr_skiplist_getlist(sl->index); p; apr_skiplist_next(sl->index, &p)) {
ni = apr_skiplist_insert((apr_skiplist *) p->data, ret->data);
apr_skiplist *sli = (apr_skiplist *)p->data;
ni = apr_skiplist_insert_compare(sli, ret->data, sli->compare);
li->nextindex = ni;
ni->previndex = li;
li = ni;
}
}
else {
/* sl->size++; */
}
sl->size++;
return ret;
}
APR_DECLARE(int) apr_skiplist_remove(apr_skiplist *sl, void *data, apr_skiplist_freefunc myfree)
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist *sl, void *data)
{
if (!sl->compare) {
return 0;
}
return apr_skiplist_remove_compare(sl, data, myfree, sl->comparek);
return apr_skiplist_insert_compare(sl, data, sl->compare);
}
#if 0
@ -520,7 +571,7 @@ static int skiplisti_remove(apr_skiplist *sl, apr_skiplistnode *m, apr_skiplist_
if (!m && myfree && p->data) {
myfree(p->data);
}
apr_skiplist_free(sl, p);
skiplist_free_node(sl, p);
}
sl->size--;
while (sl->top && sl->top->next == NULL) {
@ -530,13 +581,14 @@ static int skiplisti_remove(apr_skiplist *sl, apr_skiplistnode *m, apr_skiplist_
if (sl->top) {
sl->top->up = NULL; /* Make it think its the top */
}
apr_skiplist_free(sl, p);
skiplist_free_node(sl, p);
sl->height--;
}
if (!sl->top) {
sl->bottom = NULL;
sl->bottom = sl->bottomend = NULL;
sl->topend = NULL;
}
return sl->height; /* return 1; ?? */
return skiplist_height(sl);
}
APR_DECLARE(int) apr_skiplist_remove_compare(apr_skiplist *sli,
@ -545,11 +597,17 @@ APR_DECLARE(int) apr_skiplist_remove_compare(apr_skiplist *sli,
{
apr_skiplistnode *m;
apr_skiplist *sl;
if (!comp) {
return 0;
}
if (comp == sli->comparek || !sli->index) {
sl = sli;
}
else {
apr_skiplist_find(sli->index, (void *)comp, &m);
if (!m) {
return 0;
}
sl = (apr_skiplist *) m->data;
}
skiplisti_find_compare(sl, data, &m, comp);
@ -562,6 +620,11 @@ APR_DECLARE(int) apr_skiplist_remove_compare(apr_skiplist *sli,
return skiplisti_remove(sl, m, myfree);
}
APR_DECLARE(int) apr_skiplist_remove(apr_skiplist *sl, void *data, apr_skiplist_freefunc myfree)
{
return apr_skiplist_remove_compare(sl, data, myfree, sl->comparek);
}
APR_DECLARE(void) apr_skiplist_remove_all(apr_skiplist *sl, apr_skiplist_freefunc myfree)
{
/*
@ -573,16 +636,18 @@ APR_DECLARE(void) apr_skiplist_remove_all(apr_skiplist *sl, apr_skiplist_freefun
m = sl->bottom;
while (m) {
p = m->next;
if (p && myfree && p->data)
if (myfree && p && p->data) {
myfree(p->data);
while (m) {
u = m->up;
apr_skiplist_free(sl, p);
m = u;
}
do {
u = m->up;
skiplist_free_node(sl, m);
m = u;
} while (m);
m = p;
}
sl->top = sl->bottom = NULL;
sl->topend = sl->bottomend = NULL;
sl->height = 0;
sl->size = 0;
}
@ -611,8 +676,7 @@ APR_DECLARE(void *) apr_skiplist_peek(apr_skiplist *a)
static void skiplisti_destroy(void *vsl)
{
apr_skiplist_destroy((apr_skiplist *) vsl, NULL);
apr_skiplist_free((apr_skiplist *) vsl, vsl);
apr_skiplist_destroy(vsl, NULL);
}
APR_DECLARE(void) apr_skiplist_destroy(apr_skiplist *sl, apr_skiplist_freefunc myfree)
@ -620,6 +684,13 @@ APR_DECLARE(void) apr_skiplist_destroy(apr_skiplist *sl, apr_skiplist_freefunc m
while (apr_skiplist_pop(sl->index, skiplisti_destroy) != NULL)
;
apr_skiplist_remove_all(sl, myfree);
if (!sl->pool) {
while (sl->nodes_q.pos)
free(sl->nodes_q.data[--sl->nodes_q.pos]);
free(sl->nodes_q.data);
free(sl->stack_q.data);
free(sl);
}
}
APR_DECLARE(apr_skiplist *) apr_skiplist_merge(apr_skiplist *sl1, apr_skiplist *sl2)

View File

@ -914,8 +914,8 @@ fits_in_signed_long (offsetT num ATTRIBUTE_UNUSED)
#ifndef BFD64
return 1;
#else
return (!(((offsetT) -1 << 31) & num)
|| (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31));
return (!(-((offsetT) 1 << 31) & num)
|| (-((offsetT) 1 << 31) & num) == -((offsetT) 1 << 31));
#endif
} /* fits_in_signed_long() */

View File

@ -88,13 +88,11 @@ static struct test {
}, {
"en_US.UTF-8",
"[\001\177][\302\200\337\277][\340\240\200\357\277\277][\360\220\200"
"\200\367\277\277\277][\370\210\200\200\200\373\277\277\277\277][\374"
"\204\200\200\200\200\375\277\277\277\277\277]",
"\200\364\217\277\277]",
{ 0x5b, 0x01, 0x7f, 0x5d, 0x5b, 0x80, 0x7ff, 0x5d, 0x5b, 0x800, 0xffff,
0x5d, 0x5b, 0x10000, 0x1fffff, 0x5d, 0x5b, 0x200000, 0x3ffffff, 0x5d,
0x5b, 0x4000000, 0x7fffffff, 0x5d },
{ 1, 1, 1, 1, 1, 2, 2, 1, 1, 3, 3, 1, 1, 4, 4, 1, 1, 5, 5, 1, 1, 6, 6, 1 },
24
0x5d, 0x5b, 0x10000, 0x10ffff, 0x5d },
{ 1, 1, 1, 1, 1, 2, 2, 1, 1, 3, 3, 1, 1, 4, 4, 1 },
16
}, {
"ja_JP.ISO2022-JP2",
"\033$BF|K\1348l\033(BA\033$B$\"\033(BB\033$B$$\033(B",

View File

@ -82,12 +82,10 @@ static struct test {
{
"en_US.UTF-8",
"[\001\177][\302\200\337\277][\340\240\200\357\277\277][\360\220\200"
"\200\367\277\277\277][\370\210\200\200\200\373\277\277\277\277][\374"
"\204\200\200\200\200\375\277\277\277\277\277]",
"\200\364\217\277\277]",
{
0x5B, 0x01, 0x7F, 0x5D, 0x5B, 0x80, 0x07FF, 0x5D, 0x5B, 0x0800,
0xFFFF, 0x5D, 0x5B, 0x10000, 0x1FFFFF, 0x5D, 0x5B, 0x200000,
0x3FFFFFF, 0x5D, 0x5B, 0x4000000, 0x7FFFFFFF, 0x5D, 0x0A
0xFFFF, 0x5D, 0x5B, 0x10000, 0x10FFFF, 0x5D, 0x0A
},
{ 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1,
1, 1, -1, -1, 1, 1, -1, -1, 1, -1

View File

@ -1,10 +1,18 @@
Serf 1.3.8 [2014-10-20, from /tags/1.3.8, rxxxx]
Fix issue #152: CRC calculation error for gzipped http reponses > 4GB.
Fix issue #153: SSPI CredHandle not freed when APR pool is destroyed.
Fix issue #154: Disable SSLv2 and SSLv3 as both or broken.
Serf 1.3.7 [2014-08-11, from /tags/1.3.7, r2411]
Handle NUL bytes in fields of an X.509 certificate. (r2393, r2399)
Serf 1.3.6 [2014-06-09, from /tags/1.3.6, r2372]
Revert r2319 from serf 1.3.5: this change was making serf call handle_response
multiple times in case of an error response, leading to unexpected behavior.
Serf 1.3.5 [2014-04-27, from /tags/1.3.5, r2355]
Fix issue #125: no reverse lookup during Negotiate authentication for proxies.
Fix a crash caused by incorrect reuse of the ssltunnel CONNECT request (r2316)

View File

@ -95,8 +95,8 @@ cleanup_ctx(void *data)
}
if (SecIsValidHandle(&ctx->sspi_credentials)) {
FreeCredentialsHandle(&ctx->sspi_context);
SecInvalidateHandle(&ctx->sspi_context);
FreeCredentialsHandle(&ctx->sspi_credentials);
SecInvalidateHandle(&ctx->sspi_credentials);
}
return APR_SUCCESS;

View File

@ -141,7 +141,6 @@ static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
const char **data, apr_size_t *len)
{
deflate_context_t *ctx = bucket->data;
unsigned long compCRC, compLen;
apr_status_t status;
const char *private_data;
apr_size_t private_len;
@ -186,17 +185,25 @@ static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
ctx->state++;
break;
case STATE_VERIFY:
{
unsigned long compCRC, compLen, actualLen;
/* Do the checksum computation. */
compCRC = getLong((unsigned char*)ctx->hdr_buffer);
if (ctx->crc != compCRC) {
return SERF_ERROR_DECOMPRESSION_FAILED;
}
compLen = getLong((unsigned char*)ctx->hdr_buffer + 4);
if (ctx->zstream.total_out != compLen) {
/* The length in the trailer is module 2^32, so do the same for
the actual length. */
actualLen = ctx->zstream.total_out;
actualLen &= 0xFFFFFFFF;
if (actualLen != compLen) {
return SERF_ERROR_DECOMPRESSION_FAILED;
}
ctx->state++;
break;
}
case STATE_INIT:
zRC = inflateInit2(&ctx->zstream, ctx->windowSize);
if (zRC != Z_OK) {
@ -264,10 +271,14 @@ static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
ctx->zstream.next_in = (unsigned char*)private_data;
ctx->zstream.avail_in = private_len;
}
zRC = Z_OK;
while (ctx->zstream.avail_in != 0) {
/* We're full, clear out our buffer, reset, and return. */
if (ctx->zstream.avail_out == 0) {
while (1) {
zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
/* We're full or zlib requires more space. Either case, clear
out our buffer, reset, and return. */
if (zRC == Z_BUF_ERROR || ctx->zstream.avail_out == 0) {
serf_bucket_t *tmp;
ctx->zstream.next_out = ctx->buffer;
private_len = ctx->bufferSize - ctx->zstream.avail_out;
@ -283,7 +294,6 @@ static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
ctx->zstream.avail_out = ctx->bufferSize;
break;
}
zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
if (zRC == Z_STREAM_END) {
serf_bucket_t *tmp;
@ -330,9 +340,13 @@ static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
break;
}
/* Any other error? */
if (zRC != Z_OK) {
return SERF_ERROR_DECOMPRESSION_FAILED;
}
/* As long as zRC == Z_OK, just keep looping. */
}
/* Okay, we've inflated. Try to read. */
status = serf_bucket_read(ctx->inflate_stream, requested, data,
@ -340,8 +354,13 @@ static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
/* Hide EOF. */
if (APR_STATUS_IS_EOF(status)) {
status = ctx->stream_status;
/* If our stream is finished too, return SUCCESS so
* we'll iterate one more time.
/* If the inflation wasn't finished, return APR_SUCCESS. */
if (zRC != Z_STREAM_END)
return APR_SUCCESS;
/* If our stream is finished too and all data was inflated,
* return SUCCESS so we'll iterate one more time.
*/
if (APR_STATUS_IS_EOF(status)) {
/* No more data to read from the stream, and everything

View File

@ -1317,7 +1317,9 @@ static serf_ssl_context_t *ssl_init_context(serf_bucket_alloc_t *allocator)
ssl_ctx->pool = serf_bucket_allocator_get_pool(allocator);
ssl_ctx->allocator = allocator;
/* Use the best possible protocol version, but disable the broken SSLv2/3 */
ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert);
ssl_ctx->cached_cert = 0;

View File

@ -1062,7 +1062,7 @@ void serf_debug__bucket_alloc_check(
/* Version info */
#define SERF_MAJOR_VERSION 1
#define SERF_MINOR_VERSION 3
#define SERF_PATCH_VERSION 7
#define SERF_PATCH_VERSION 8
/* Version number string */
#define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \

View File

@ -6,9 +6,9 @@ libsqlite3_la_SOURCES = sqlite3.c
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
bin_PROGRAMS = sqlite3
sqlite3_SOURCES = shell.c sqlite3.h
sqlite3_LDADD = $(top_builddir)/libsqlite3.la @READLINE_LIBS@
sqlite3_DEPENDENCIES = $(top_builddir)/libsqlite3.la
sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h
sqlite3_LDADD = @READLINE_LIBS@
sqlite3_CFLAGS = $(AM_CFLAGS)
include_HEADERS = sqlite3.h sqlite3ext.h

View File

@ -107,8 +107,12 @@ libsqlite3_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libsqlite3_la_LDFLAGS) $(LDFLAGS) -o $@
PROGRAMS = $(bin_PROGRAMS)
am_sqlite3_OBJECTS = shell.$(OBJEXT)
am_sqlite3_OBJECTS = sqlite3-shell.$(OBJEXT) sqlite3-sqlite3.$(OBJEXT)
sqlite3_OBJECTS = $(am_sqlite3_OBJECTS)
sqlite3_DEPENDENCIES =
sqlite3_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(sqlite3_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@ -272,9 +276,9 @@ AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -D
lib_LTLIBRARIES = libsqlite3.la
libsqlite3_la_SOURCES = sqlite3.c
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
sqlite3_SOURCES = shell.c sqlite3.h
sqlite3_LDADD = $(top_builddir)/libsqlite3.la @READLINE_LIBS@
sqlite3_DEPENDENCIES = $(top_builddir)/libsqlite3.la
sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h
sqlite3_LDADD = @READLINE_LIBS@
sqlite3_CFLAGS = $(AM_CFLAGS)
include_HEADERS = sqlite3.h sqlite3ext.h
EXTRA_DIST = sqlite3.1 tea
pkgconfigdir = ${libdir}/pkgconfig
@ -402,7 +406,7 @@ clean-binPROGRAMS:
rm -f $$list
sqlite3$(EXEEXT): $(sqlite3_OBJECTS) $(sqlite3_DEPENDENCIES) $(EXTRA_sqlite3_DEPENDENCIES)
@rm -f sqlite3$(EXEEXT)
$(LINK) $(sqlite3_OBJECTS) $(sqlite3_LDADD) $(LIBS)
$(sqlite3_LINK) $(sqlite3_OBJECTS) $(sqlite3_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@ -410,7 +414,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sqlite3-shell.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sqlite3-sqlite3.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sqlite3.Plo@am__quote@
.c.o:
@ -434,6 +439,34 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
sqlite3-shell.o: shell.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -MT sqlite3-shell.o -MD -MP -MF $(DEPDIR)/sqlite3-shell.Tpo -c -o sqlite3-shell.o `test -f 'shell.c' || echo '$(srcdir)/'`shell.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sqlite3-shell.Tpo $(DEPDIR)/sqlite3-shell.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='shell.c' object='sqlite3-shell.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -c -o sqlite3-shell.o `test -f 'shell.c' || echo '$(srcdir)/'`shell.c
sqlite3-shell.obj: shell.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -MT sqlite3-shell.obj -MD -MP -MF $(DEPDIR)/sqlite3-shell.Tpo -c -o sqlite3-shell.obj `if test -f 'shell.c'; then $(CYGPATH_W) 'shell.c'; else $(CYGPATH_W) '$(srcdir)/shell.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sqlite3-shell.Tpo $(DEPDIR)/sqlite3-shell.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='shell.c' object='sqlite3-shell.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -c -o sqlite3-shell.obj `if test -f 'shell.c'; then $(CYGPATH_W) 'shell.c'; else $(CYGPATH_W) '$(srcdir)/shell.c'; fi`
sqlite3-sqlite3.o: sqlite3.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -MT sqlite3-sqlite3.o -MD -MP -MF $(DEPDIR)/sqlite3-sqlite3.Tpo -c -o sqlite3-sqlite3.o `test -f 'sqlite3.c' || echo '$(srcdir)/'`sqlite3.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sqlite3-sqlite3.Tpo $(DEPDIR)/sqlite3-sqlite3.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sqlite3.c' object='sqlite3-sqlite3.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -c -o sqlite3-sqlite3.o `test -f 'sqlite3.c' || echo '$(srcdir)/'`sqlite3.c
sqlite3-sqlite3.obj: sqlite3.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -MT sqlite3-sqlite3.obj -MD -MP -MF $(DEPDIR)/sqlite3-sqlite3.Tpo -c -o sqlite3-sqlite3.obj `if test -f 'sqlite3.c'; then $(CYGPATH_W) 'sqlite3.c'; else $(CYGPATH_W) '$(srcdir)/sqlite3.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sqlite3-sqlite3.Tpo $(DEPDIR)/sqlite3-sqlite3.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sqlite3.c' object='sqlite3-sqlite3.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sqlite3_CFLAGS) $(CFLAGS) -c -o sqlite3-sqlite3.obj `if test -f 'sqlite3.c'; then $(CYGPATH_W) 'sqlite3.c'; else $(CYGPATH_W) '$(srcdir)/sqlite3.c'; fi`
mostlyclean-libtool:
-rm -f *.lo

View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.8.9.
# Generated by GNU Autoconf 2.69 for sqlite 3.8.11.1.
#
# Report bugs to <http://www.sqlite.org>.
#
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.8.9'
PACKAGE_STRING='sqlite 3.8.9'
PACKAGE_VERSION='3.8.11.1'
PACKAGE_STRING='sqlite 3.8.11.1'
PACKAGE_BUGREPORT='http://www.sqlite.org'
PACKAGE_URL=''
@ -1313,7 +1313,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.8.9 to adapt to many kinds of systems.
\`configure' configures sqlite 3.8.11.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1383,7 +1383,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.8.9:";;
short | recursive ) echo "Configuration of sqlite 3.8.11.1:";;
esac
cat <<\_ACEOF
@ -1489,7 +1489,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.8.9
sqlite configure 3.8.11.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1813,7 +1813,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.8.9, which was
It was created by sqlite $as_me 3.8.11.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2631,7 +2631,7 @@ fi
# Define the identity of the package.
PACKAGE='sqlite'
VERSION='3.8.9'
VERSION='3.8.11.1'
cat >>confdefs.h <<_ACEOF
@ -13196,7 +13196,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.8.9, which was
This file was extended by sqlite $as_me 3.8.11.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -13253,7 +13253,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.8.9
sqlite config.status 3.8.11.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -8,7 +8,7 @@
#
AC_PREREQ(2.61)
AC_INIT(sqlite, 3.8.9, http://www.sqlite.org)
AC_INIT(sqlite, 3.8.11.1, http://www.sqlite.org)
AC_CONFIG_SRCDIR([sqlite3.c])
# Use automake.

View File

@ -101,28 +101,26 @@
#if defined(_WIN32) || defined(WIN32)
# include <io.h>
# include <fcntl.h>
#define isatty(h) _isatty(h)
#ifndef access
# define access(f,m) _access((f),(m))
#endif
#undef popen
#define popen _popen
#undef pclose
#define pclose _pclose
# define isatty(h) _isatty(h)
# ifndef access
# define access(f,m) _access((f),(m))
# endif
# undef popen
# define popen _popen
# undef pclose
# define pclose _pclose
#else
/* Make sure isatty() has a prototype.
*/
extern int isatty(int);
#if !defined(__RTP__) && !defined(_WRS_KERNEL)
/* popen and pclose are not C89 functions and so are sometimes omitted from
** the <stdio.h> header */
extern FILE *popen(const char*,const char*);
extern int pclose(FILE*);
#else
# define SQLITE_OMIT_POPEN 1
#endif
/* Make sure isatty() has a prototype. */
extern int isatty(int);
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
/* popen and pclose are not C89 functions and so are
** sometimes omitted from the <stdio.h> header */
extern FILE *popen(const char*,const char*);
extern int pclose(FILE*);
# else
# define SQLITE_OMIT_POPEN 1
# endif
#endif
#if defined(_WIN32_WCE)
@ -336,7 +334,7 @@ static int stdin_is_interactive = 1;
** to this database a static variable so that it can be accessed
** by the SIGINT handler to interrupt database processing.
*/
static sqlite3 *db = 0;
static sqlite3 *globalDb = 0;
/*
** True if an interrupt (Control-C) has been received.
@ -527,6 +525,7 @@ struct ShellState {
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
int statsOn; /* True to display memory stats before each finalize */
int scanstatsOn; /* True to display scan stats before each finalize */
int backslashOn; /* Resolve C-style \x escapes in SQL input text */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
@ -804,7 +803,7 @@ static void interrupt_handler(int NotUsed){
UNUSED_PARAMETER(NotUsed);
seenInterrupt++;
if( seenInterrupt>2 ) exit(1);
if( db ) sqlite3_interrupt(db);
if( globalDb ) sqlite3_interrupt(globalDb);
}
#endif
@ -989,7 +988,16 @@ static int shell_callback(
case MODE_Insert: {
p->cnt++;
if( azArg==0 ) break;
fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
fprintf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
fprintf(p->out,"(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
fprintf(p->out, "%s%s", zSep, azCol[i]);
}
fprintf(p->out,")");
}
fprintf(p->out," VALUES(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
@ -1190,7 +1198,7 @@ static char *save_err_msg(
sqlite3 *db /* Database to query */
){
int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
char *zErrMsg = sqlite3_malloc(nErrMsg);
char *zErrMsg = sqlite3_malloc64(nErrMsg);
if( zErrMsg ){
memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
}
@ -1321,7 +1329,10 @@ static void display_scanstats(
sqlite3 *db, /* Database to query */
ShellState *pArg /* Pointer to ShellState */
){
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pArg);
#else
int i, k, n, mx;
fprintf(pArg->out, "-------- scanstats --------\n");
mx = 0;
@ -1427,8 +1438,8 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int));
p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
@ -1545,7 +1556,7 @@ static int shell_exec(
if( xCallback ){
/* allocate space for col name ptr, value ptr, and type */
int nCol = sqlite3_column_count(pStmt);
void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1);
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
if( !pData ){
rc = SQLITE_NOMEM;
}else{
@ -1771,6 +1782,7 @@ static int run_schema_dump_query(
static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
".bail on|off Stop after hitting an error. Default OFF\n"
".binary on|off Turn binary output on or off. Default OFF\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dbinfo ?DB? Show status information about the database\n"
@ -1792,6 +1804,7 @@ static char zHelp[] =
#ifdef SQLITE_ENABLE_IOTRACE
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
#endif
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
#endif
@ -1854,6 +1867,7 @@ static void readfileFunc(
long nIn;
void *pBuf;
UNUSED_PARAMETER(argc);
zName = (const char*)sqlite3_value_text(argv[0]);
if( zName==0 ) return;
in = fopen(zName, "rb");
@ -1861,7 +1875,7 @@ static void readfileFunc(
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc( nIn );
pBuf = sqlite3_malloc64( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
}else{
@ -1886,6 +1900,7 @@ static void writefileFunc(
sqlite3_int64 rc;
const char *zFile;
UNUSED_PARAMETER(argc);
zFile = (const char*)sqlite3_value_text(argv[0]);
if( zFile==0 ) return;
out = fopen(zFile, "wb");
@ -1908,23 +1923,23 @@ static void open_db(ShellState *p, int keepAlive){
if( p->db==0 ){
sqlite3_initialize();
sqlite3_open(p->zDbFilename, &p->db);
db = p->db;
if( db && sqlite3_errcode(db)==SQLITE_OK ){
sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
globalDb = p->db;
if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
shellstaticFunc, 0, 0);
}
if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
p->zDbFilename, sqlite3_errmsg(db));
p->zDbFilename, sqlite3_errmsg(p->db));
if( keepAlive ) return;
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0,
readfileFunc, 0, 0);
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0,
writefileFunc, 0, 0);
}
}
@ -1932,26 +1947,44 @@ static void open_db(ShellState *p, int keepAlive){
/*
** Do C-language style dequoting.
**
** \a -> alarm
** \b -> backspace
** \t -> tab
** \n -> newline
** \v -> vertical tab
** \f -> form feed
** \r -> carriage return
** \s -> space
** \" -> "
** \NNN -> ascii character NNN in octal
** \' -> '
** \\ -> backslash
** \NNN -> ascii character NNN in octal
*/
static void resolve_backslashes(char *z){
int i, j;
char c;
while( *z && *z!='\\' ) z++;
for(i=j=0; (c = z[i])!=0; i++, j++){
if( c=='\\' ){
if( c=='\\' && z[i+1]!=0 ){
c = z[++i];
if( c=='n' ){
c = '\n';
if( c=='a' ){
c = '\a';
}else if( c=='b' ){
c = '\b';
}else if( c=='t' ){
c = '\t';
}else if( c=='n' ){
c = '\n';
}else if( c=='v' ){
c = '\v';
}else if( c=='f' ){
c = '\f';
}else if( c=='r' ){
c = '\r';
}else if( c=='"' ){
c = '"';
}else if( c=='\'' ){
c = '\'';
}else if( c=='\\' ){
c = '\\';
}else if( c>='0' && c<='7' ){
@ -2121,7 +2154,7 @@ struct ImportCtx {
static void import_append_char(ImportCtx *p, int c){
if( p->n+1>=p->nAlloc ){
p->nAlloc += p->nAlloc + 100;
p->z = sqlite3_realloc(p->z, p->nAlloc);
p->z = sqlite3_realloc64(p->z, p->nAlloc);
if( p->z==0 ){
fprintf(stderr, "out of memory\n");
exit(1);
@ -2135,7 +2168,7 @@ static void import_append_char(ImportCtx *p, int c){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** from sqlite3_malloc64().
** + Use p->cSep as the column separator. The default is ",".
** + Use p->rSep as the row separator. The default is "\n".
** + Keep track of the line number in p->nLine.
@ -2209,7 +2242,7 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** from sqlite3_malloc64().
** + Use p->cSep as the column separator. The default is "\x1F".
** + Use p->rSep as the row separator. The default is "\x1E".
** + Keep track of the row number in p->nLine.
@ -2269,7 +2302,7 @@ static void tryToCloneData(
goto end_data_xfer;
}
n = sqlite3_column_count(pQuery);
zInsert = sqlite3_malloc(200 + nTable + n*3);
zInsert = sqlite3_malloc64(200 + nTable + n*3);
if( zInsert==0 ){
fprintf(stderr, "out of memory\n");
goto end_data_xfer;
@ -2547,7 +2580,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
for(i=0; i<sizeof(aField)/sizeof(aField[0]); i++){
for(i=0; i<ArraySize(aField); i++){
int ofst = aField[i].ofst;
unsigned int val = get4byteInt(aHdr + ofst);
fprintf(p->out, "%-20s %u", aField[i].zName, val);
@ -2567,7 +2600,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
}else{
zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
}
for(i=0; i<sizeof(aQuery)/sizeof(aQuery[0]); i++){
for(i=0; i<ArraySize(aQuery); i++){
char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
int val = db_int(p, zSql);
sqlite3_free(zSql);
@ -2585,7 +2618,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, ShellState *p){
int i = 1;
int h = 1;
int nArg = 0;
int n, c;
int rc = 0;
@ -2593,24 +2626,24 @@ static int do_meta_command(char *zLine, ShellState *p){
/* Parse the input line into tokens.
*/
while( zLine[i] && nArg<ArraySize(azArg) ){
while( IsSpace(zLine[i]) ){ i++; }
if( zLine[i]==0 ) break;
if( zLine[i]=='\'' || zLine[i]=='"' ){
int delim = zLine[i++];
azArg[nArg++] = &zLine[i];
while( zLine[i] && zLine[i]!=delim ){
if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++;
i++;
while( zLine[h] && nArg<ArraySize(azArg) ){
while( IsSpace(zLine[h]) ){ h++; }
if( zLine[h]==0 ) break;
if( zLine[h]=='\'' || zLine[h]=='"' ){
int delim = zLine[h++];
azArg[nArg++] = &zLine[h];
while( zLine[h] && zLine[h]!=delim ){
if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
h++;
}
if( zLine[i]==delim ){
zLine[i++] = 0;
if( zLine[h]==delim ){
zLine[h++] = 0;
}
if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
}else{
azArg[nArg++] = &zLine[i];
while( zLine[i] && !IsSpace(zLine[i]) ){ i++; }
if( zLine[i] ) zLine[i++] = 0;
azArg[nArg++] = &zLine[h];
while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
if( zLine[h] ) zLine[h++] = 0;
resolve_backslashes(azArg[nArg-1]);
}
}
@ -2685,6 +2718,19 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
setBinaryMode(p->out);
}else{
setTextMode(p->out);
}
}else{
fprintf(stderr, "Usage: .binary on|off\n");
rc = 1;
}
}else
/* The undocumented ".breakpoint" command causes a call to the no-op
** routine named test_breakpoint().
*/
@ -2986,7 +3032,7 @@ static int do_meta_command(char *zLine, ShellState *p){
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
@ -3006,7 +3052,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zCreate);
if( rc ){
fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
sqlite3_errmsg(db));
sqlite3_errmsg(p->db));
sqlite3_free(sCtx.z);
xCloser(sCtx.in);
return 1;
@ -3016,7 +3062,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zSql);
if( rc ){
if (pStmt) sqlite3_finalize(pStmt);
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
xCloser(sCtx.in);
return 1;
}
@ -3024,7 +3070,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_finalize(pStmt);
pStmt = 0;
if( nCol==0 ) return 0; /* no columns, no error */
zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 );
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
if( zSql==0 ){
fprintf(stderr, "Error: out of memory\n");
xCloser(sCtx.in);
@ -3041,13 +3087,13 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
if (pStmt) sqlite3_finalize(pStmt);
xCloser(sCtx.in);
return 1;
}
needCommit = sqlite3_get_autocommit(db);
if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
needCommit = sqlite3_get_autocommit(p->db);
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
do{
int startLine = sCtx.nLine;
for(i=0; i<nCol; i++){
@ -3086,7 +3132,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK ){
fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine,
sqlite3_errmsg(db));
sqlite3_errmsg(p->db));
}
}
}while( sCtx.cTerm!=EOF );
@ -3094,7 +3140,7 @@ static int do_meta_command(char *zLine, ShellState *p){
xCloser(sCtx.in);
sqlite3_free(sCtx.z);
sqlite3_finalize(pStmt);
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
}else
if( c=='i' && (strncmp(azArg[0], "indices", n)==0
@ -3164,6 +3210,64 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#endif
if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
static const struct {
const char *zLimitName; /* Name of a limit */
int limitCode; /* Integer code for that limit */
} aLimit[] = {
{ "length", SQLITE_LIMIT_LENGTH },
{ "sql_length", SQLITE_LIMIT_SQL_LENGTH },
{ "column", SQLITE_LIMIT_COLUMN },
{ "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
{ "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
{ "vdbe_op", SQLITE_LIMIT_VDBE_OP },
{ "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
{ "attached", SQLITE_LIMIT_ATTACHED },
{ "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
{ "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
{ "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
};
int i, n2;
open_db(p, 0);
if( nArg==1 ){
for(i=0; i<ArraySize(aLimit); i++){
printf("%20s %d\n", aLimit[i].zLimitName,
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
}
}else if( nArg>3 ){
fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
rc = 1;
goto meta_command_exit;
}else{
int iLimit = -1;
n2 = strlen30(azArg[1]);
for(i=0; i<ArraySize(aLimit); i++){
if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
if( iLimit<0 ){
iLimit = i;
}else{
fprintf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
rc = 1;
goto meta_command_exit;
}
}
}
if( iLimit<0 ){
fprintf(stderr, "unknown limit: \"%s\"\n"
"enter \".limits\" with no arguments for a list.\n",
azArg[1]);
rc = 1;
goto meta_command_exit;
}
if( nArg==3 ){
sqlite3_limit(p->db, aLimit[iLimit].limitCode,
(int)integerValue(azArg[2]));
}
printf("%20s %d\n", aLimit[iLimit].zLimitName,
sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
}
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
@ -3248,9 +3352,8 @@ static int do_meta_command(char *zLine, ShellState *p){
const char *zSavedFilename = p->zDbFilename;
char *zNewFilename = 0;
p->db = 0;
if( nArg>=2 ){
p->zDbFilename = zNewFilename = sqlite3_mprintf("%s", azArg[1]);
}
if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]);
p->zDbFilename = zNewFilename;
open_db(p, 1);
if( p->db!=0 ){
sqlite3_close(savedDb);
@ -3648,13 +3751,13 @@ static int do_meta_command(char *zLine, ShellState *p){
while( sqlite3_step(pStmt)==SQLITE_ROW ){
if( nRow>=nAlloc ){
char **azNew;
int n = nAlloc*2 + 10;
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n);
int n2 = nAlloc*2 + 10;
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
if( azNew==0 ){
fprintf(stderr, "Error: out of memory\n");
break;
}
nAlloc = n;
nAlloc = n2;
azResult = azNew;
}
azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
@ -3707,15 +3810,15 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
};
int testctrl = -1;
int rc = 0;
int i, n;
int rc2 = 0;
int i, n2;
open_db(p, 0);
/* convert testctrl text option to value. allow any unique prefix
** of the option name, or a numerical value. */
n = strlen30(azArg[1]);
for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
n2 = strlen30(azArg[1]);
for(i=0; i<ArraySize(aCtrl); i++){
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
if( testctrl<0 ){
testctrl = aCtrl[i].ctrlCode;
}else{
@ -3736,8 +3839,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_RESERVE:
if( nArg==3 ){
int opt = (int)strtol(azArg[2], 0, 0);
rc = sqlite3_test_control(testctrl, p->db, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, p->db, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
@ -3750,8 +3853,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_BYTEORDER:
if( nArg==2 ){
rc = sqlite3_test_control(testctrl);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
}
@ -3761,8 +3864,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_PENDING_BYTE:
if( nArg==3 ){
unsigned int opt = (unsigned int)integerValue(azArg[2]);
rc = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single unsigned"
" int option\n", azArg[1]);
@ -3775,8 +3878,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_NEVER_CORRUPT:
if( nArg==3 ){
int opt = booleanValue(azArg[2]);
rc = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
@ -3788,8 +3891,8 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_ISKEYWORD:
if( nArg==3 ){
const char *opt = azArg[2];
rc = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
rc2 = sqlite3_test_control(testctrl, opt);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
azArg[1]);
@ -3799,11 +3902,11 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_IMPOSTER:
if( nArg==5 ){
rc = sqlite3_test_control(testctrl, p->db,
rc2 = sqlite3_test_control(testctrl, p->db,
azArg[2],
integerValue(azArg[3]),
integerValue(azArg[4]));
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
}else{
fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
}
@ -4111,6 +4214,7 @@ static int process_input(ShellState *p, FILE *in){
&& sqlite3_complete(zSql) ){
p->cnt = 0;
open_db(p, 0);
if( p->backslashOn ) resolve_backslashes(zSql);
BEGIN_TIMER;
rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
END_TIMER;
@ -4577,6 +4681,13 @@ int SQLITE_CDECL main(int argc, char **argv){
data.statsOn = 1;
}else if( strcmp(z,"-scanstats")==0 ){
data.scanstatsOn = 1;
}else if( strcmp(z,"-backslash")==0 ){
/* Undocumented command-line option: -backslash
** Causes C-style backslash escapes to be evaluated in SQL statements
** prior to sending the SQL into SQLite. Useful for injecting
** crazy bytes in the middle of SQL statements for testing and debugging.
*/
data.backslashOn = 1;
}else if( strcmp(z,"-bail")==0 ){
bail_on_error = 1;
}else if( strcmp(z,"-version")==0 ){
@ -4683,7 +4794,7 @@ int SQLITE_CDECL main(int argc, char **argv){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
}
}
if( zHistory ) shell_read_history(zHistory);
if( zHistory ){ shell_read_history(zHistory); }
rc = process_input(&data, 0);
if( zHistory ){
shell_stifle_history(100);

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
**
** The official C-language API documentation for SQLite is derived
** from comments in this file. This file is the authoritative source
** on how SQLite interfaces are suppose to operate.
** on how SQLite interfaces are supposed to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
@ -111,9 +111,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.9"
#define SQLITE_VERSION_NUMBER 3008009
#define SQLITE_SOURCE_ID "2015-04-08 12:16:33 8a8ffc862e96f57aa698f93de10dee28e69f6e09"
#define SQLITE_VERSION "3.8.11.1"
#define SQLITE_VERSION_NUMBER 3008011
#define SQLITE_SOURCE_ID "2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -270,6 +270,7 @@ typedef sqlite_uint64 sqlite3_uint64;
/*
** CAPI3REF: Closing A Database Connection
** DESTRUCTOR: sqlite3
**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
@ -321,6 +322,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
/*
** CAPI3REF: One-Step Query Execution Interface
** METHOD: sqlite3
**
** The sqlite3_exec() interface is a convenience wrapper around
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
@ -961,6 +963,14 @@ struct sqlite3_io_methods {
** circumstances in order to fix a problem with priority inversion.
** Applications should <em>not</em> use this file-control.
**
** <li>[[SQLITE_FCNTL_ZIPVFS]]
** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
** VFS should return SQLITE_NOTFOUND for this opcode.
**
** <li>[[SQLITE_FCNTL_RBU]]
** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
** this opcode.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@ -986,6 +996,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
#define SQLITE_FCNTL_WAL_BLOCK 24
#define SQLITE_FCNTL_ZIPVFS 25
#define SQLITE_FCNTL_RBU 26
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@ -1378,6 +1390,7 @@ SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...);
/*
** CAPI3REF: Configure database connections
** METHOD: sqlite3
**
** The sqlite3_db_config() interface is used to make configuration
** changes to a [database connection]. The interface is similar to
@ -1875,6 +1888,7 @@ struct sqlite3_mem_methods {
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
** METHOD: sqlite3
**
** ^The sqlite3_extended_result_codes() routine enables or disables the
** [extended result codes] feature of SQLite. ^The extended result
@ -1884,6 +1898,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff)
/*
** CAPI3REF: Last Insert Rowid
** METHOD: sqlite3
**
** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
** has a unique 64-bit signed
@ -1935,6 +1950,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*);
/*
** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlite3
**
** ^This function returns the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
@ -1987,6 +2003,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*);
/*
** CAPI3REF: Total Number Of Rows Modified
** METHOD: sqlite3
**
** ^This function returns the total number of rows inserted, modified or
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
@ -2010,6 +2027,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*);
/*
** CAPI3REF: Interrupt A Long-Running Query
** METHOD: sqlite3
**
** ^This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
@ -2086,6 +2104,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
** KEYWORDS: {busy-handler callback} {busy handler}
** METHOD: sqlite3
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
@ -2145,6 +2164,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int),
/*
** CAPI3REF: Set A Busy Timeout
** METHOD: sqlite3
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked. ^The handler
@ -2167,6 +2187,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms);
/*
** CAPI3REF: Convenience Routines For Running Queries
** METHOD: sqlite3
**
** This is a legacy interface that is preserved for backwards compatibility.
** Use of this interface is not recommended.
@ -2502,6 +2523,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P);
/*
** CAPI3REF: Compile-Time Authorization Callbacks
** METHOD: sqlite3
**
** ^This routine registers an authorizer callback with a particular
** [database connection], supplied in the first argument.
@ -2658,6 +2680,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer(
/*
** CAPI3REF: Tracing And Profiling Functions
** METHOD: sqlite3
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
@ -2690,6 +2713,7 @@ SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*,
/*
** CAPI3REF: Query Progress Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to
@ -2723,6 +2747,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(vo
/*
** CAPI3REF: Opening A New Database Connection
** CONSTRUCTOR: sqlite3
**
** ^These routines open an SQLite database file as specified by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
@ -3008,6 +3033,7 @@ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const cha
/*
** CAPI3REF: Error Codes And Messages
** METHOD: sqlite3
**
** ^If the most recent sqlite3_* API call associated with
** [database connection] D failed, then the sqlite3_errcode(D) interface
@ -3053,33 +3079,34 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int);
/*
** CAPI3REF: SQL Statement Object
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement.
** This object is variously known as a "prepared statement" or a
** "compiled SQL statement" or simply as a "statement".
** An instance of this object represents a single SQL statement that
** has been compiled into binary form and is ready to be evaluated.
**
** The life of a statement object goes something like this:
** Think of each SQL statement as a separate computer program. The
** original SQL text is source code. A prepared statement object
** is the compiled object code. All SQL must be converted into a
** prepared statement before it can be run.
**
** The life-cycle of a prepared statement object usually goes like this:
**
** <ol>
** <li> Create the object using [sqlite3_prepare_v2()] or a related
** function.
** <li> Bind values to [host parameters] using the sqlite3_bind_*()
** <li> Create the prepared statement object using [sqlite3_prepare_v2()].
** <li> Bind values to [parameters] using the sqlite3_bind_*()
** interfaces.
** <li> Run the SQL by calling [sqlite3_step()] one or more times.
** <li> Reset the statement using [sqlite3_reset()] then go back
** <li> Reset the prepared statement using [sqlite3_reset()] then go back
** to step 2. Do this zero or more times.
** <li> Destroy the object using [sqlite3_finalize()].
** </ol>
**
** Refer to documentation on individual methods above for additional
** information.
*/
typedef struct sqlite3_stmt sqlite3_stmt;
/*
** CAPI3REF: Run-time Limits
** METHOD: sqlite3
**
** ^(This interface allows the size of various constructs to be limited
** on a connection by connection basis. The first parameter is the
@ -3191,6 +3218,8 @@ SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
** METHOD: sqlite3
** CONSTRUCTOR: sqlite3_stmt
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
@ -3298,6 +3327,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2(
/*
** CAPI3REF: Retrieving Statement SQL
** METHOD: sqlite3_stmt
**
** ^This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
@ -3307,6 +3337,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
@ -3338,6 +3369,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using
@ -3368,7 +3400,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*);
** Some interfaces require a protected sqlite3_value. Other interfaces
** will accept either a protected or an unprotected sqlite3_value.
** Every interface that accepts sqlite3_value arguments specifies
** whether or not it requires a protected sqlite3_value.
** whether or not it requires a protected sqlite3_value. The
** [sqlite3_value_dup()] interface can be used to construct a new
** protected sqlite3_value from an unprotected sqlite3_value.
**
** The terms "protected" and "unprotected" refer to whether or not
** a mutex is held. An internal mutex is held for a protected
@ -3412,6 +3446,7 @@ typedef struct sqlite3_context sqlite3_context;
** CAPI3REF: Binding Values To Prepared Statements
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
** METHOD: sqlite3_stmt
**
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
** literals may be replaced by a [parameter] that matches one of following
@ -3527,9 +3562,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char
void(*)(void*), unsigned char encoding);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
/*
** CAPI3REF: Number Of SQL Parameters
** METHOD: sqlite3_stmt
**
** ^This routine can be used to find the number of [SQL parameters]
** in a [prepared statement]. SQL parameters are tokens of the
@ -3550,6 +3587,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*);
/*
** CAPI3REF: Name Of A Host Parameter
** METHOD: sqlite3_stmt
**
** ^The sqlite3_bind_parameter_name(P,N) interface returns
** the name of the N-th [SQL parameter] in the [prepared statement] P.
@ -3577,6 +3615,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*,
/*
** CAPI3REF: Index Of A Parameter With A Given Name
** METHOD: sqlite3_stmt
**
** ^Return the index of an SQL parameter given its name. ^The
** index value returned is suitable for use as the second
@ -3593,6 +3632,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const
/*
** CAPI3REF: Reset All Bindings On A Prepared Statement
** METHOD: sqlite3_stmt
**
** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
** the [sqlite3_bind_blob | bindings] on a [prepared statement].
@ -3602,6 +3642,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*);
/*
** CAPI3REF: Number Of Columns In A Result Set
** METHOD: sqlite3_stmt
**
** ^Return the number of columns in the result set returned by the
** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
@ -3613,6 +3654,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Column Names In A Result Set
** METHOD: sqlite3_stmt
**
** ^These routines return the name assigned to a particular column
** in the result set of a [SELECT] statement. ^The sqlite3_column_name()
@ -3642,6 +3684,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N
/*
** CAPI3REF: Source Of Data In A Query Result
** METHOD: sqlite3_stmt
**
** ^These routines provide a means to determine the database, table, and
** table column that is the origin of a particular result column in
@ -3694,6 +3737,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*
/*
** CAPI3REF: Declared Datatype Of A Query Result
** METHOD: sqlite3_stmt
**
** ^(The first parameter is a [prepared statement].
** If this statement is a [SELECT] statement and the Nth column of the
@ -3726,6 +3770,7 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,in
/*
** CAPI3REF: Evaluate An SQL Statement
** METHOD: sqlite3_stmt
**
** After a [prepared statement] has been prepared using either
** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
@ -3805,6 +3850,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*);
/*
** CAPI3REF: Number of columns in a result set
** METHOD: sqlite3_stmt
**
** ^The sqlite3_data_count(P) interface returns the number of columns in the
** current row of the result set of [prepared statement] P.
@ -3858,8 +3904,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Result Values From A Query
** KEYWORDS: {column access functions}
**
** These routines form the "result set" interface.
** METHOD: sqlite3_stmt
**
** ^These routines return information about a single column of the current
** result row of a query. ^In every case the first argument is a pointer
@ -3920,13 +3965,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
** even empty strings, are always zero-terminated. ^The return
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
**
** ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. In a multithreaded environment,
** an unprotected sqlite3_value object may only be used safely with
** [sqlite3_bind_value()] and [sqlite3_result_value()].
** If the [unprotected sqlite3_value] object returned by
** [sqlite3_column_value()] is used in any other way, including calls
** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
** or [sqlite3_value_bytes()], then the behavior is undefined.
** or [sqlite3_value_bytes()], the behavior is not threadsafe.
**
** These routines attempt to convert the value where appropriate. ^For
** example, if the internal representation is FLOAT and a text result
@ -3957,12 +4003,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
** </table>
** </blockquote>)^
**
** The table above makes reference to standard C library functions atoi()
** and atof(). SQLite does not really use these functions. It has its
** own equivalent internal routines. The atoi() and atof() names are
** used in the table for brevity and because they are familiar to most
** C programmers.
**
** Note that when type conversions occur, pointers returned by prior
** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
** sqlite3_column_text16() may be invalidated.
@ -3987,7 +4027,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
** of conversion are done in place when it is possible, but sometimes they
** are not possible and in those cases prior pointers are invalidated.
**
** The safest and easiest to remember policy is to invoke these routines
** The safest policy is to invoke these routines
** in one of the following ways:
**
** <ul>
@ -4007,7 +4047,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
** ^The pointers returned are valid until a type conversion occurs as
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
** and BLOBs is freed automatically. Do <em>not</em> pass the pointers returned
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
@ -4030,6 +4070,7 @@ SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int
/*
** CAPI3REF: Destroy A Prepared Statement Object
** DESTRUCTOR: sqlite3_stmt
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
@ -4057,6 +4098,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Reset A Prepared Statement Object
** METHOD: sqlite3_stmt
**
** The sqlite3_reset() function is called to reset a [prepared statement]
** object back to its initial state, ready to be re-executed.
@ -4086,6 +4128,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt);
** KEYWORDS: {function creation routines}
** KEYWORDS: {application-defined SQL function}
** KEYWORDS: {application-defined SQL functions}
** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
** are used to add SQL functions or aggregates or to redefine the behavior
@ -4254,11 +4297,12 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi
#endif
/*
** CAPI3REF: Obtaining SQL Function Parameter Values
** CAPI3REF: Obtaining SQL Values
** METHOD: sqlite3_value
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
** the function or aggregate.
** the function or aggregate.
**
** The xFunc (for scalar functions) or xStep (for aggregates) parameters
** to [sqlite3_create_function()] and [sqlite3_create_function16()]
@ -4311,8 +4355,26 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*);
SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*);
/*
** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
** memory allocation fails.
**
** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
** then sqlite3_value_free(V) is a harmless no-op.
*/
SQLITE_API SQLITE_EXPERIMENTAL sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*);
SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*);
/*
** CAPI3REF: Obtain Aggregate Function Context
** METHOD: sqlite3_context
**
** Implementations of aggregate SQL functions use this
** routine to allocate memory for storing their state.
@ -4357,6 +4419,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int
/*
** CAPI3REF: User Data For Functions
** METHOD: sqlite3_context
**
** ^The sqlite3_user_data() interface returns a copy of
** the pointer that was the pUserData parameter (the 5th parameter)
@ -4371,6 +4434,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*);
/*
** CAPI3REF: Database Connection For Functions
** METHOD: sqlite3_context
**
** ^The sqlite3_context_db_handle() interface returns a copy of
** the pointer to the [database connection] (the 1st parameter)
@ -4382,6 +4446,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data
** METHOD: sqlite3_context
**
** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
@ -4454,6 +4519,7 @@ typedef void (*sqlite3_destructor_type)(void*);
/*
** CAPI3REF: Setting The Result Of An SQL Function
** METHOD: sqlite3_context
**
** These routines are used by the xFunc or xFinal callbacks that
** implement SQL functions and aggregates. See
@ -4469,9 +4535,9 @@ typedef void (*sqlite3_destructor_type)(void*);
** to by the second parameter and which is N bytes long where N is the
** third parameter.
**
** ^The sqlite3_result_zeroblob() interfaces set the result of
** the application-defined function to be a BLOB containing all zero
** bytes and N bytes in size, where N is the value of the 2nd parameter.
** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N)
** interfaces set the result of the application-defined function to be
** a BLOB containing all zero bytes and N bytes in size.
**
** ^The sqlite3_result_double() interface sets the result from
** an application-defined function to be a floating point value specified
@ -4553,7 +4619,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** from [sqlite3_malloc()] before it returns.
**
** ^The sqlite3_result_value() interface sets the result of
** the application-defined function to be a copy the
** the application-defined function to be a copy of the
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
** so that the [sqlite3_value] specified in the parameter may change or
@ -4586,9 +4652,11 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const v
SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*);
SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n);
SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
**
** ^These functions add, remove, or modify a [collation] associated
** with the [database connection] specified as the first argument.
@ -4691,6 +4759,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16(
/*
** CAPI3REF: Collation Needed Callbacks
** METHOD: sqlite3
**
** ^To avoid having to register all collation sequences before a database
** can be used, a single callback function may be registered with the
@ -4898,6 +4967,7 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
/*
** CAPI3REF: Test For Auto-Commit Mode
** KEYWORDS: {autocommit mode}
** METHOD: sqlite3
**
** ^The sqlite3_get_autocommit() interface returns non-zero or
** zero if the given database connection is or is not in autocommit mode,
@ -4920,6 +4990,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*);
/*
** CAPI3REF: Find The Database Handle Of A Prepared Statement
** METHOD: sqlite3_stmt
**
** ^The sqlite3_db_handle interface returns the [database connection] handle
** to which a [prepared statement] belongs. ^The [database connection]
@ -4932,6 +5003,7 @@ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*);
/*
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D. ^The main database file
@ -4948,6 +5020,7 @@ SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const cha
/*
** CAPI3REF: Determine if a database is read-only
** METHOD: sqlite3
**
** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
** of connection D is read-only, 0 if it is read/write, or -1 if N is not
@ -4957,6 +5030,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbNa
/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
**
** ^This interface returns a pointer to the next [prepared statement] after
** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@ -4972,6 +5046,7 @@ SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_
/*
** CAPI3REF: Commit And Rollback Notification Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_commit_hook() interface registers a callback
** function to be invoked whenever a transaction is [COMMIT | committed].
@ -5021,6 +5096,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *),
/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
@ -5127,6 +5203,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int);
/*
** CAPI3REF: Free Memory Used By A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
** memory as possible from database connection D. Unlike the
@ -5204,6 +5281,7 @@ SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N);
/*
** CAPI3REF: Extract Metadata About A Column Of A Table
** METHOD: sqlite3
**
** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
** information about column C of table T in database D
@ -5282,6 +5360,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata(
/*
** CAPI3REF: Load An Extension
** METHOD: sqlite3
**
** ^This interface loads an SQLite extension library from the named file.
**
@ -5323,6 +5402,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_load_extension(
/*
** CAPI3REF: Enable Or Disable Extension Loading
** METHOD: sqlite3
**
** ^So as not to open security holes in older applications that are
** unprepared to deal with [extension loading], and as a means of disabling
@ -5572,6 +5652,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Register A Virtual Table Implementation
** METHOD: sqlite3
**
** ^These routines are used to register a new [virtual table module] name.
** ^Module names must be registered before
@ -5668,6 +5749,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL);
/*
** CAPI3REF: Overload A Function For A Virtual Table
** METHOD: sqlite3
**
** ^(Virtual tables can provide alternative implementations of functions
** using the [xFindFunction] method of the [virtual table module].
@ -5710,6 +5792,8 @@ typedef struct sqlite3_blob sqlite3_blob;
/*
** CAPI3REF: Open A BLOB For Incremental I/O
** METHOD: sqlite3
** CONSTRUCTOR: sqlite3_blob
**
** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
** in row iRow, column zColumn, table zTable in database zDb;
@ -5791,6 +5875,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
/*
** CAPI3REF: Move a BLOB Handle to a New Row
** METHOD: sqlite3_blob
**
** ^This function is used to move an existing blob handle so that it points
** to a different row of the same database table. ^The new row is identified
@ -5811,10 +5896,11 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
**
** ^This function sets the database handle error code and message.
*/
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
/*
** CAPI3REF: Close A BLOB Handle
** DESTRUCTOR: sqlite3_blob
**
** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
** unconditionally. Even if this routine returns an error code, the
@ -5837,6 +5923,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *);
/*
** CAPI3REF: Return The Size Of An Open BLOB
** METHOD: sqlite3_blob
**
** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
@ -5852,6 +5939,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *);
/*
** CAPI3REF: Read Data From A BLOB Incrementally
** METHOD: sqlite3_blob
**
** ^(This function is used to read data from an open [BLOB handle] into a
** caller-supplied buffer. N bytes of data are copied into buffer Z
@ -5880,6 +5968,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N,
/*
** CAPI3REF: Write Data Into A BLOB Incrementally
** METHOD: sqlite3_blob
**
** ^(This function is used to write data into an open [BLOB handle] from a
** caller-supplied buffer. N bytes of data are copied from the buffer Z
@ -6204,9 +6293,13 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */
#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */
#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */
/*
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
**
** ^This interface returns a pointer the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
@ -6218,6 +6311,7 @@ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*);
/*
** CAPI3REF: Low-Level Control Of Database Files
** METHOD: sqlite3
**
** ^The [sqlite3_file_control()] interface makes a direct call to the
** xFileControl method for the [sqlite3_io_methods] object associated
@ -6434,6 +6528,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_status64(
/*
** CAPI3REF: Database Connection Status
** METHOD: sqlite3
**
** ^This interface is used to retrieve runtime status information
** about a single [database connection]. ^The first argument is the
@ -6562,6 +6657,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int
/*
** CAPI3REF: Prepared Statement Status
** METHOD: sqlite3_stmt
**
** ^(Each prepared statement maintains various
** [SQLITE_STMTSTATUS counters] that measure the number
@ -7065,6 +7161,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p);
/*
** CAPI3REF: Unlock Notification
** METHOD: sqlite3
**
** ^When running in shared-cache mode, a database operation may fail with
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
@ -7235,6 +7332,7 @@ SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...)
/*
** CAPI3REF: Write-Ahead Log Commit Hook
** METHOD: sqlite3
**
** ^The [sqlite3_wal_hook()] function is used to register a callback that
** is invoked each time data is committed to a database in wal mode.
@ -7274,6 +7372,7 @@ SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook(
/*
** CAPI3REF: Configure an auto-checkpoint
** METHOD: sqlite3
**
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
** [sqlite3_wal_hook()] that causes any database on [database connection] D
@ -7304,6 +7403,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
/*
** CAPI3REF: Checkpoint a database
** METHOD: sqlite3
**
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
@ -7325,6 +7425,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zD
/*
** CAPI3REF: Checkpoint a database
** METHOD: sqlite3
**
** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint
** operation on database X of [database connection] D in mode M. Status
@ -7579,6 +7680,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Prepared Statement Scan Status
** METHOD: sqlite3_stmt
**
** This interface returns information about the predicted and measured
** performance for pStmt. Advanced applications can use this
@ -7607,7 +7709,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *);
**
** See also: [sqlite3_stmt_scanstatus_reset()]
*/
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus(
SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
@ -7616,13 +7718,14 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus(
/*
** CAPI3REF: Zero Scan-Status Counters
** METHOD: sqlite3_stmt
**
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
@ -7737,6 +7840,8 @@ struct sqlite3_rtree_query_info {
int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
};
/*

View File

@ -267,6 +267,11 @@ struct sqlite3_api_routines {
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
};
/*
@ -497,6 +502,11 @@ struct sqlite3_api_routines {
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
#endif /* SQLITE_CORE */
#ifndef SQLITE_CORE

View File

@ -1,3 +1,138 @@
Version 1.8.14
(5 Aug 2015, from /branches/1.8.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.14
User-visible changes:
- Client-side bugfixes:
* document svn:autoprops (r1678494 et al.)
* cp: fix 'svn cp ^/A/D/H@1 ^/A' to properly create A (r1674455, r1674456)
* resolve: improve conflict prompts for binary files (r1667228 et al.)
* ls: improve performance of '-v' on tag directories (r1673153)
* improved Sqlite 3.8.9 query performance regression on externals (r1672295 et al.)
* fixed issue #4580: 'svn -v st' on file externals reports "?" instead
of user and revision after 'svn up' (r1680242)
- Server-side bugfixes:
* mod_dav_svn: do not ignore skel parsing errors (r1658168)
* detect invalid svndiff data earlier (r1684077)
* prevent possible repository corruption on power/disk failures (r1680819)
* fixed issue #4577: Read error with nodes whose DELTA chain starts with
a PLAIN rep (r1676667, r1677267)
* fixed issue #4531: server-side copy (over dav) is slow and uses
too much memory (r1674627)
Developer-visible changes:
- General:
* support building on Windows with Visual Studio 2015 (r1692785)
* avoid failing some tests on versions of Python with a very old sqlite (r1674522)
* fix Ruby tests so they don't use the users real configuration (r1597884)
- Bindings:
* swig-pl: fix some stack memory problems (r1668618, 1671388)
Version 1.8.13
(31 Mar 2015, from /branches/1.8.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.13
User-visible changes:
- Client-side bugfixes:
* ra_serf: prevent abort of commits that have already succeeded (r1659867)
* ra_serf: support case-insensitivity in HTTP headers (r1650481, r1650489)
* better error message if an external is shadowed (r1655712, r1655738)
* ra_svn: fix reporting of directory read errors (r1656713)
* fix a redirect handling bug in 'svn log' over HTTP (r1650531)
* properly copy tree conflict information (r1658115, r1659553, r1659554)
* fix 'svn patch' output for reordered hunks (issue #4533)
* svnrdump load: don't load wrong props with no-deltas dump (issue #4551)
* fix working copy corruption with relative file external (issue #4411)
* don't crash if config file is unreadable (r1590751, r1660350)
* svn resolve: don't ask a question with only one answer (r1658417)
* fix assertion failure in svn move (r1651963 et al)
* working copy performance improvements (r1664531, r1664476, et al)
* handle existing working copies which become externals (r1660071)
* fix recording of WC meta-data for foreign repos copies (r1660593)
* fix calculating repository path of replaced directories (r1660646)
* fix calculating repository path after commit of switched nodes (r1663991)
* svnrdump: don't provide HEAD+1 as base revision for deletes (r1664684)
* don't leave conflict markers on files that are moved (r1660220, r1665874)
* avoid unnecessary subtree mergeinfo recording (r1666690)
* fix diff of a locally copied directory with props (r1619380 et al)
- Server-side bugfixes:
* fsfs: fix a problem verifying pre-1.4 repos used with 1.8 (r1561419)
* svnadmin freeze: fix memory allocation error (r1653039)
* svnadmin load: tolerate invalid mergeinfo at r0 (r1643074, issue #4476)
* svnadmin load: strip references to r1 from mergeinfo (issue #4538)
* svnsync: strip any r0 references from mergeinfo (issue #4476)
* fsfs: reduce memory consumption when operating on dag nodes (r1655651)
* reject invalid get-location-segments requests in mod_dav_svn and
svnserve (r1667233)
* mod_dav_svn: reject invalid txnprop change requests (r1667235)
- Client-side and server-side bugfixes:
* fix undefined behaviour in string buffer routines (r1650834)
* fix consistency issues with APR r/w locks on Windows (r1611380 et al)
* fix occasional SEGV if threads load DSOs in parallel (r1659013, r1659315)
* properly duplicate svn error objects (r1651759)
* fix use-after-free in config parser (1646785, r1646786, r1646797)
Developer-visible changes:
* add lock file config for testing against HTTPD 2.4+ (r1544302, r1544303)
* make sqlite amalgamated build work with sqlite 3.8.x+ (r1659399)
* fix build with Ruby 2 (r1596882)
* process 'svnadmin dump' output as binary in the test suite (r1592987)
* simplify Windows resource compilation to avoid warnings (r1532287)
Version 1.8.12
(Not released, see changes for 1.8.13.)
Version 1.8.11
(15 Dec 2014, from /branches/1.8.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.11
User-visible changes:
- Client-side bugfixes:
* checkout/update: fix file externals failing to follow history and
subsequently silently failing (issue #4185)
* patch: don't skip targets in valid --git difs (r1592014, r1592034)
* diff: make property output in diffs stable (r1589360)
* diff: fix diff of local copied directory with props (r1619380, r1619393)
* diff: fix changelist filter for repos-WC and WC-WC (r1621978, r1621981)
* remove broken conflict resolver menu options that always error out
(r1620332)
* improve gpg-agent support (r1600331, r1600348, 1600368, r1600563,
r1600781)
* fix crash in eclipse IDE with GNOME Keyring (issue #3498)
* fix externals shadowing a versioned directory (issue #4085)
* fix problems working on unix file systems that don't support
permissions (r1612225)
* upgrade: keep external registrations (issue #4519)
* cleanup: iprove performance of recorded timestamp fixups (r1633126)
* translation updates for German
- Server-side bugfixes:
* disable revprop caching feature due to cache invalidation problems
(r1543594, r1619774, r1619105, r1619118, r1619153, r1619802)
* skip generating uniquifiers if rep-sharing is not supported (r1561426)
* mod_dav_svn: reject requests with missing repository paths (r1643409)
* mod_dav_svn: reject requests with invalid virtual transaction names
(r1643437)
* mod_dav_svn: avoid unneeded memory growth in resource walking
(issue #4531)
Developer-visible changes:
- General:
* make sure all members of the repos layer notify struct are valid,
fixes crashes in API users using all members (r1616131)
* properly generate a version resource when building on Windows (r1542610,
r1564576, r1568180)
* fix LIBTOOL_M4 and LIBTOOL_CONFIG variable not be evaluated properly
during a unix build (r1637826)
* allow the use of libtool 2.4.3 (r1640862, r1640873, r1643793)
Version 1.8.10
(11 Aug 2014, from /branches/1.8.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.10
@ -316,7 +451,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.8.1
* merge: rename 'automatic merge' to 'complete merge' (r1491432)
* mergeinfo: reduce network usage for '--show-revs' (r1492005)
* ra_serf: improve http status handling (r1495104)
* merge: avoid unneeded ra session (r1493475)
* merge: avoid unneeded RA session (r1493475)
* merge: reduce network usage (r1478987)
* merge: remove duplicated ancestry check (r1493424, r1495597)
* ra_serf: fix 'Accept-Encoding' header for IIS interoperability (r1497551)
@ -729,6 +864,81 @@ http://svn.apache.org/repos/asf/subversion/tags/1.8.0
* fix some reference counting bugs in swig-py bindings (r1464899, r1466524)
Version 1.7.21
(5 Aug 2015, from /branches/1.7.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.21
User-visible changes:
- Client-side bugfixes:
* cp: fix 'svn cp ^/A/D/H@1 ^/A' to properly create A (r1674455, r1674456)
* fix issue #4551: svnrdump load commits wrong properties, or fails, on a
non-deltas dumpfile (r1652182 et al.)
- Server-side bugfixes:
* fix 'svnadmin recover' for pre-1.4 FSFS repositories (r1561419)
Developer-visible changes:
- General:
* support building on Windows with Visual Studio 2012, 2013 and 2015 (r1687158, r1692783)
- Bindings:
* swig-pl: fix some stack memory problems (r1668618, 1671388)
Version 1.7.20
(31 Mar 2015, from /branches/1.7.x)
http://svn.apache.org/repos/asf/subversion/tags/1.7.20
User-visible changes:
- Client-side bugfixes:
* fix 'svn patch' output for reordered hunks (issue #4533)
- Server-side bugfixes:
* reject invalid get-location-segments requests in mod_dav_svn and
svnserve (r1667233)
* mod_dav_svn: reject invalid txnprop change requests (r1667235)
- Client-side and server-side bugfixes:
* properly duplicate svn error objects (r1651759)
* fix use-after-free in config parser (1646785, r1646786, r1646797)
Developer-visible changes:
* add lock file config for testing against HTTPD 2.4+ (r1544302, r1544303)
* fix build with absolute path to neon install (r1664789)
Version 1.7.19
(15 Dec 2014, from /branches/1.7.x)
http://svn.apache.org/repos/asf/subversion/tags/1.7.19
User-visible changes:
- Client-side bugfixes:
* rm: display the proper URL in commit log editor (r1591123)
* diff: fix invalid read during suffix scanning (issue #4339)
* fix crash in eclipse IDE with GNOME Keyring (issue #3498)
* checkout/update: fix file externals failing to follow history and
subsequently silently failing (issue #4185)
- Server-side bugfixes:
* svnadmin dump: don't let invalid mergeinfo prevent a dump (issue #4476)
* mod_dav_svn: reject requests with missing repository paths (r1643409)
* mod_dav_svn: reject requests with invalid virtual transaction names
(r1643437)
* mod_dav_svn: avoid unneeded memory growth in resource walking
(issue #4531)
Developer-visible changes:
- General:
* properly generate a version resource when building on Windows (r1542610,
r1564576, r1568180)
* fix a problem with the unix build that could result in linking to the
wrong Subversion libraries at build or at run time (r1594157)
* use a proper intermediate directory when building with Visual Studio
2003-2008 (r1595431)
* fix LIBTOOL_M4 and LIBTOOL_CONFIG variable not be evaluated properly
during a unix build (r1637826)
* allow the use of libtool 2.4.3 (r1640862, r1640873, r1643793)
Version 1.7.18
(11 Aug 2014, from /branches/1.7.x)
http://svn.apache.org/repos/asf/subversion/tags/1.7.18

View File

@ -357,6 +357,7 @@ TEST_SHLIB_VAR_SWIG_RB=\
fi;
APXS = @APXS@
HTTPD_VERSION = @HTTPD_VERSION@
PYTHON = @PYTHON@
PERL = @PERL@
@ -509,6 +510,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@
if test "$(HTTP_LIBRARY)" != ""; then \
flags="--http-library $(HTTP_LIBRARY) $$flags"; \
fi; \
if test "$(HTTPD_VERSION)" != ""; then \
flags="--httpd-version $(HTTPD_VERSION) $$flags"; \
fi; \
if test "$(SERVER_MINOR_VERSION)" != ""; then \
flags="--server-minor-version $(SERVER_MINOR_VERSION) $$flags"; \
fi; \

View File

@ -1,5 +1,5 @@
Apache Subversion
Copyright 2014 The Apache Software Foundation
Copyright 2015 The Apache Software Foundation
This product includes software developed by many people, and distributed
under Contributor License Agreements to The Apache Software Foundation

View File

@ -23,6 +23,10 @@
### Run this to produce everything needed for configuration. ###
# Some shells can produce output when running 'cd' which interferes
# with the construct 'abs=`cd dir && pwd`'.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Run tests to ensure that our build requirements are met
RELEASE_MODE=""
RELEASE_ARGS=""
@ -71,48 +75,80 @@ rm -f build/config.guess build/config.sub
$libtoolize --copy --automake --force
ltpath="`dirname $libtoolize`"
ltfile=${LIBTOOL_M4-`cd $ltpath/../share/aclocal ; pwd`/libtool.m4}
if [ ! -f $ltfile ]; then
echo "$ltfile not found (try setting the LIBTOOL_M4 environment variable)"
if [ "x$LIBTOOL_M4" = "x" ]; then
ltm4_error='(try setting the LIBTOOL_M4 environment variable)'
if [ -d "$ltpath/../share/aclocal/." ]; then
ltm4=`cd "$ltpath/../share/aclocal" && pwd`
else
echo "Libtool helper path not found $ltm4_error"
echo " expected at: '$ltpath/../share/aclocal'"
exit 1
fi
else
ltm4_error="(the LIBTOOL_M4 environment variable is: $LIBTOOL_M4)"
ltm4="$LIBTOOL_M4"
fi
ltfile="$ltm4/libtool.m4"
if [ ! -f "$ltfile" ]; then
echo "$ltfile not found $ltm4_error"
exit 1
fi
echo "Copying libtool helper: $ltfile"
echo "Copying libtool helper: $ltfile"
# An ancient helper might already be present from previous builds,
# and it might be write-protected (e.g. mode 444, seen on FreeBSD).
# This would cause cp to fail and print an error message, but leave
# behind a potentially outdated libtool helper. So, remove before
# copying:
rm -f build/libtool.m4
cp $ltfile build/libtool.m4
cp "$ltfile" build/libtool.m4
for file in ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4; do
rm -f build/$file
if [ $lt_major_version -ge 2 ]; then
ltfile=${LIBTOOL_M4-`cd $ltpath/../share/aclocal ; pwd`/$file}
ltfile="$ltm4/$file"
if [ ! -f $ltfile ]; then
echo "$ltfile not found (try setting the LIBTOOL_M4 environment variable)"
if [ ! -f "$ltfile" ]; then
echo "$ltfile not found $ltm4_error"
exit 1
fi
echo "Copying libtool helper: $ltfile"
cp $ltfile build/$file
echo "Copying libtool helper: $ltfile"
cp "$ltfile" "build/$file"
fi
done
if [ $lt_major_version -ge 2 ]; then
for file in config.guess config.sub; do
configfile=${LIBTOOL_CONFIG-`cd $ltpath/../share/libtool/config ; pwd`/$file}
if [ "x$LIBTOOL_CONFIG" = "x" ]; then
ltconfig_error='(try setting the LIBTOOL_CONFIG environment variable)'
if [ -d "$ltpath/../share/libtool/config/." ]; then
ltconfig=`cd "$ltpath/../share/libtool/config" && pwd`
elif [ -d "$ltpath/../share/libtool/build-aux/." ]; then
ltconfig=`cd "$ltpath/../share/libtool/build-aux" && pwd`
else
echo "Autoconf helper path not found $ltconfig_error"
echo " expected at: '$ltpath/../share/libtool/config'"
echo " or: '$ltpath/../share/libtool/build-aux'"
exit 1
fi
else
ltconfig_error="(the LIBTOOL_CONFIG environment variable is: $LIBTOOL_CONFIG)"
ltconfig="$LIBTOOL_CONFIG"
fi
if [ ! -f $configfile ]; then
echo "$configfile not found (try setting the LIBTOOL_CONFIG environment variable)"
for file in config.guess config.sub; do
configfile="$ltconfig/$file"
if [ ! -f "$configfile" ]; then
echo "$configfile not found $ltconfig_error"
exit 1
fi
cp $configfile build/$file
echo "Copying autoconf helper: $configfile"
cp "$configfile" build/$file
done
fi

File diff suppressed because one or more lines are too long

View File

@ -1357,6 +1357,7 @@ install = tools
libs = libsvn_repos libsvn_fs libsvn_subr apr
[svn-populate-node-origins-index]
description = Tool to populate the node origins index of a repository
type = exe
path = tools/server-side
sources = svn-populate-node-origins-index.c

File diff suppressed because it is too large Load Diff

View File

@ -1246,7 +1246,7 @@ AC_PATH_PROG(PERL, perl, none)
if test -n "$RUBY"; then
AC_PATH_PROG(RUBY, "$RUBY", none)
else
AC_PATH_PROGS(RUBY, ruby ruby1.8 ruby18 ruby1.9 ruby1 ruby1.9.3 ruby193, none)
AC_PATH_PROGS(RUBY, ruby ruby1.8 ruby18 ruby1.9 ruby1 ruby1.9.3 ruby193 ruby2.0 ruby2.1, none)
fi
if test "$RUBY" != "none"; then
AC_MSG_CHECKING([rb_hash_foreach])
@ -1255,7 +1255,7 @@ if test "$RUBY" != "none"; then
if test -n "$RDOC"; then
AC_PATH_PROG(RDOC, "$RDOC", none)
else
AC_PATH_PROGS(RDOC, rdoc rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193, none)
AC_PATH_PROGS(RDOC, rdoc rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193 rdoc2.0 rdoc2.1, none)
fi
AC_CACHE_CHECK([for Ruby major version], [svn_cv_ruby_major],[
svn_cv_ruby_major="`$RUBY -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(MAJOR))'`"

View File

@ -33,7 +33,7 @@
APR_VERSION=${APR_VERSION:-"1.4.6"}
APU_VERSION=${APU_VERSION:-"1.5.1"}
SERF_VERSION=${SERF_VERSION:-"1.3.4"}
SERF_VERSION=${SERF_VERSION:-"1.3.8"}
ZLIB_VERSION=${ZLIB_VERSION:-"1.2.8"}
SQLITE_VERSION=${SQLITE_VERSION:-"3.7.15.1"}
GTEST_VERSION=${GTEST_VERSION:-"1.6.0"}

View File

@ -97,7 +97,7 @@ svn_diff__unidiff_write_header(svn_stream_t *output_stream,
* merged or reverse merged; otherwise (or if the mergeinfo property values
* don't parse correctly) display them just like any other property.
*
* Use @a pool for temporary allocations.
* Use @a scratch_pool for temporary allocations.
*/
svn_error_t *
svn_diff__display_prop_diffs(svn_stream_t *outstream,
@ -105,7 +105,7 @@ svn_diff__display_prop_diffs(svn_stream_t *outstream,
const apr_array_header_t *propchanges,
apr_hash_t *original_props,
svn_boolean_t pretty_print_mergeinfo,
apr_pool_t *pool);
apr_pool_t *scratch_pool);
#ifdef __cplusplus

View File

@ -65,6 +65,27 @@ svn_error_t *
svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
apr_pool_t *scratch_pool);
/** Canonicalize the @a rangelist: sort the ranges, and combine adjacent or
* overlapping ranges into single ranges where possible.
*
* If overlapping ranges have different inheritability, return an error.
*
* Modify @a rangelist in place. Use @a scratch_pool for temporary
* allocations.
*/
svn_error_t *
svn_rangelist__canonicalize(svn_rangelist_t *rangelist,
apr_pool_t *scratch_pool);
/** Canonicalize the revision range lists in the @a mergeinfo.
*
* Modify @a mergeinfo in place. Use @a scratch_pool for temporary
* allocations.
*/
svn_error_t *
svn_mergeinfo__canonicalize_ranges(svn_mergeinfo_t mergeinfo,
apr_pool_t *scratch_pool);
/* Set inheritability of all rangelists in MERGEINFO to INHERITABLE.
If MERGEINFO is NULL do nothing. If a rangelist in MERGEINFO is
NULL leave it alone. */

View File

@ -113,6 +113,10 @@ svn_repos__replay_ev2(svn_fs_root_t *root,
void *authz_read_baton,
apr_pool_t *scratch_pool);
/* A private addition to svn_repos_notify_warning_t. */
#define svn_repos__notify_warning_invalid_mergeinfo \
((svn_repos_notify_warning_t)(-1))
#ifdef __cplusplus
}

View File

@ -484,6 +484,32 @@ svn_sqlite__with_immediate_transaction(svn_sqlite__db_t *db,
SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err)); \
} while (0)
/* Evaluate the expression EXPR1..EXPR4 within a 'savepoint'. Savepoints can
* be nested.
*
* Begin a savepoint in DB; evaluate the expression EXPR1, which would
* typically be a function call that does some work in DB; if no error occurred,
* run EXPR2; if no error occurred EXPR3; ... and finally release
* the savepoint if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
* to the savepoint and then release it.
*/
#define SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, db) \
do { \
svn_sqlite__db_t *svn_sqlite__db = (db); \
svn_error_t *svn_sqlite__err; \
\
SVN_ERR(svn_sqlite__begin_savepoint(svn_sqlite__db)); \
svn_sqlite__err = (expr1); \
if (!svn_sqlite__err) \
svn_sqlite__err = (expr2); \
if (!svn_sqlite__err) \
svn_sqlite__err = (expr3); \
if (!svn_sqlite__err) \
svn_sqlite__err = (expr4); \
SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err)); \
} while (0)
/* Helper function to handle several SQLite operations inside a shared lock.
This callback is similar to svn_sqlite__with_transaction(), but can be
nested (even with a transaction).

View File

@ -1148,6 +1148,8 @@ svn_stream_read(svn_stream_t *stream,
* of reads or a simple seek operation. If the stream implementation has
* not provided a skip function, this will read from the stream and
* discard the data.
*
* @since New in 1.7.
*/
svn_error_t *
svn_stream_skip(svn_stream_t *stream,

View File

@ -28,15 +28,13 @@
#define SVN_VERSION_H
/* Hack to prevent the resource compiler from including
apr_general.h. It doesn't resolve the include paths
correctly and blows up without this.
*/
#ifndef APR_STRINGIFY
apr and other headers. */
#ifndef SVN_WIN32_RESOURCE_COMPILATION
#include <apr_general.h>
#endif
#include <apr_tables.h>
#include "svn_types.h"
#endif
#ifdef __cplusplus
extern "C" {
@ -72,7 +70,7 @@ extern "C" {
*
* @since New in 1.1.
*/
#define SVN_VER_PATCH 10
#define SVN_VER_PATCH 14
/** @deprecated Provided for backward compatibility with the 1.0 API. */
@ -95,7 +93,7 @@ extern "C" {
*
* Always change this at the same time as SVN_VER_NUMTAG.
*/
#define SVN_VER_TAG " (r1615264)"
#define SVN_VER_TAG " (r1692801)"
/** Number tag: a string describing the version.
@ -121,7 +119,7 @@ extern "C" {
* When rolling a tarball, we automatically replace it with what we
* guess to be the correct revision number.
*/
#define SVN_VER_REVISION 1615264
#define SVN_VER_REVISION 1692801
/* Version strings composed from the above definitions. */

View File

@ -49,120 +49,19 @@
/*-----------------------------------------------------------------------*/
struct gnome_keyring_baton
{
const char *keyring_name;
GnomeKeyringInfo *info;
GMainLoop *loop;
};
/* Callback function to destroy gnome_keyring_baton. */
static void
callback_destroy_data_keyring(void *data)
{
struct gnome_keyring_baton *key_info = data;
if (data == NULL)
return;
free((void*)key_info->keyring_name);
key_info->keyring_name = NULL;
if (key_info->info)
{
gnome_keyring_info_free(key_info->info);
key_info->info = NULL;
}
return;
}
/* Callback function to complete the keyring operation. */
static void
callback_done(GnomeKeyringResult result,
gpointer data)
{
struct gnome_keyring_baton *key_info = data;
g_main_loop_quit(key_info->loop);
return;
}
/* Callback function to get the keyring info. */
static void
callback_get_info_keyring(GnomeKeyringResult result,
GnomeKeyringInfo *info,
void *data)
{
struct gnome_keyring_baton *key_info = data;
if (result == GNOME_KEYRING_RESULT_OK && info != NULL)
{
key_info->info = gnome_keyring_info_copy(info);
}
else
{
if (key_info->info != NULL)
gnome_keyring_info_free(key_info->info);
key_info->info = NULL;
}
g_main_loop_quit(key_info->loop);
return;
}
/* Callback function to get the default keyring string name. */
static void
callback_default_keyring(GnomeKeyringResult result,
const char *string,
void *data)
{
struct gnome_keyring_baton *key_info = data;
if (result == GNOME_KEYRING_RESULT_OK && string != NULL)
{
key_info->keyring_name = strdup(string);
}
else
{
free((void*)key_info->keyring_name);
key_info->keyring_name = NULL;
}
g_main_loop_quit(key_info->loop);
return;
}
/* Returns the default keyring name, allocated in RESULT_POOL. */
static char*
get_default_keyring_name(apr_pool_t *result_pool)
{
char *def = NULL;
struct gnome_keyring_baton key_info;
char *name, *def;
GnomeKeyringResult gkr;
key_info.info = NULL;
key_info.keyring_name = NULL;
gkr = gnome_keyring_get_default_keyring_sync(&name);
if (gkr != GNOME_KEYRING_RESULT_OK)
return NULL;
/* Finds default keyring. */
key_info.loop = g_main_loop_new(NULL, FALSE);
gnome_keyring_get_default_keyring(callback_default_keyring, &key_info, NULL);
g_main_loop_run(key_info.loop);
if (key_info.keyring_name == NULL)
{
callback_destroy_data_keyring(&key_info);
return NULL;
}
def = apr_pstrdup(result_pool, key_info.keyring_name);
callback_destroy_data_keyring(&key_info);
def = apr_pstrdup(result_pool, name);
g_free(name);
return def;
}
@ -171,28 +70,22 @@ get_default_keyring_name(apr_pool_t *result_pool)
static svn_boolean_t
check_keyring_is_locked(const char *keyring_name)
{
struct gnome_keyring_baton key_info;
GnomeKeyringInfo *info;
svn_boolean_t locked;
GnomeKeyringResult gkr;
key_info.info = NULL;
key_info.keyring_name = NULL;
/* Get details about the default keyring. */
key_info.loop = g_main_loop_new(NULL, FALSE);
gnome_keyring_get_info(keyring_name, callback_get_info_keyring, &key_info,
NULL);
g_main_loop_run(key_info.loop);
if (key_info.info == NULL)
{
callback_destroy_data_keyring(&key_info);
return FALSE;
}
/* Check if keyring is locked. */
if (gnome_keyring_info_get_is_locked(key_info.info))
return TRUE;
else
gkr = gnome_keyring_get_info_sync(keyring_name, &info);
if (gkr != GNOME_KEYRING_RESULT_OK)
return FALSE;
if (gnome_keyring_info_get_is_locked(info))
locked = TRUE;
else
locked = FALSE;
gnome_keyring_info_free(info);
return locked;
}
/* Unlock the KEYRING_NAME with the KEYRING_PASSWORD. If KEYRING was
@ -202,34 +95,19 @@ unlock_gnome_keyring(const char *keyring_name,
const char *keyring_password,
apr_pool_t *pool)
{
struct gnome_keyring_baton key_info;
GnomeKeyringInfo *info;
GnomeKeyringResult gkr;
key_info.info = NULL;
key_info.keyring_name = NULL;
/* Get details about the default keyring. */
key_info.loop = g_main_loop_new(NULL, FALSE);
gnome_keyring_get_info(keyring_name, callback_get_info_keyring,
&key_info, NULL);
g_main_loop_run(key_info.loop);
if (key_info.info == NULL)
{
callback_destroy_data_keyring(&key_info);
return FALSE;
}
else
{
key_info.loop = g_main_loop_new(NULL, FALSE);
gnome_keyring_unlock(keyring_name, keyring_password,
callback_done, &key_info, NULL);
g_main_loop_run(key_info.loop);
}
callback_destroy_data_keyring(&key_info);
if (check_keyring_is_locked(keyring_name))
gkr = gnome_keyring_get_info_sync(keyring_name, &info);
if (gkr != GNOME_KEYRING_RESULT_OK)
return FALSE;
return TRUE;
gkr = gnome_keyring_unlock_sync(keyring_name, keyring_password);
gnome_keyring_info_free(info);
if (gkr != GNOME_KEYRING_RESULT_OK)
return FALSE;
return check_keyring_is_locked(keyring_name);
}

View File

@ -1006,7 +1006,10 @@ repos_to_repos_copy(const apr_array_header_t *copy_pairs,
&& (relpath != NULL && *relpath != '\0'))
{
info->resurrection = TRUE;
top_url = svn_uri_dirname(top_url, pool);
top_url = svn_uri_get_longest_ancestor(
top_url,
svn_uri_dirname(pair->dst_abspath_or_url, pool),
pool);
SVN_ERR(svn_ra_reparent(ra_session, top_url, pool));
}
}

View File

@ -146,6 +146,7 @@ relegate_dir_external(svn_wc_context_t *wc_ctx,
static svn_error_t *
switch_dir_external(const char *local_abspath,
const char *url,
const char *url_from_externals_definition,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
const char *defining_abspath,
@ -169,6 +170,46 @@ switch_dir_external(const char *local_abspath,
if (revision->kind == svn_opt_revision_number)
external_rev = revision->value.number;
/*
* The code below assumes existing versioned paths are *not* part of
* the external's defining working copy.
* The working copy library does not support registering externals
* on top of existing BASE nodes and will error out if we try.
* So if the external target is part of the defining working copy's
* BASE tree, don't attempt to create the external. Doing so would
* leave behind a switched path instead of an external (since the
* switch succeeds but registration of the external in the DB fails).
* The working copy then cannot be updated until the path is switched back.
* See issue #4085.
*/
SVN_ERR(svn_wc__node_get_base(&kind, NULL, NULL,
&repos_root_url, &repos_uuid,
NULL, ctx->wc_ctx, local_abspath,
TRUE, /* ignore_enoent */
TRUE, /* show hidden */
pool, pool));
if (kind != svn_node_unknown)
{
const char *wcroot_abspath;
const char *defining_wcroot_abspath;
SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx,
local_abspath, pool, pool));
SVN_ERR(svn_wc__get_wcroot(&defining_wcroot_abspath, ctx->wc_ctx,
defining_abspath, pool, pool));
if (strcmp(wcroot_abspath, defining_wcroot_abspath) == 0)
return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
_("The external '%s' defined in %s at '%s' "
"cannot be checked out because '%s' is "
"already a versioned path."),
url_from_externals_definition,
SVN_PROP_EXTERNALS,
svn_dirent_local_style(defining_abspath,
pool),
svn_dirent_local_style(local_abspath,
pool));
}
/* If path is a directory, try to update/switch to the correct URL
and revision. */
SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
@ -201,6 +242,20 @@ switch_dir_external(const char *local_abspath,
FALSE, TRUE,
timestamp_sleep,
ctx, subpool));
/* We just decided that this existing directory is an external,
so update the external registry with this information, like
when checking out an external */
SVN_ERR(svn_wc__external_register(ctx->wc_ctx,
defining_abspath,
local_abspath, svn_node_dir,
repos_root_url, repos_uuid,
svn_uri_skip_ancestor(repos_root_url,
url, pool),
external_peg_rev,
external_rev,
pool));
svn_pool_destroy(subpool);
goto cleanup;
}
@ -460,7 +515,10 @@ switch_file_external(const char *local_abspath,
svn_dirent_split(&dir_abspath, &target, local_abspath, scratch_pool);
/* Open an RA session to 'source' URL */
/* ### Why do we open a new session? RA_SESSION is a valid
### session -- the caller used it to call svn_ra_check_path on
### this very URL, the caller also did the resolving and
### reparenting that is repeated here. */
SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &switch_loc,
url, dir_abspath,
peg_revision, revision,
@ -497,7 +555,7 @@ switch_file_external(const char *local_abspath,
invalid revnum, that means RA will use the latest revision. */
SVN_ERR(svn_ra_do_switch3(ra_session, &reporter, &report_baton,
switch_loc->rev,
target, svn_depth_unknown, url,
target, svn_depth_unknown, switch_loc->url,
FALSE /* send_copyfrom */,
TRUE /* ignore_ancestry */,
switch_editor, switch_baton,
@ -738,6 +796,7 @@ handle_external_item_change(svn_client_ctx_t *ctx,
{
case svn_node_dir:
SVN_ERR(switch_dir_external(local_abspath, new_loc->url,
new_item->url,
&(new_item->peg_revision),
&(new_item->revision),
parent_dir_abspath,

View File

@ -814,10 +814,12 @@ svn_client_log5(const apr_array_header_t *targets,
svn_ra_session_t *ra_session;
const char *old_session_url;
const char *ra_target;
const char *path_or_url;
svn_opt_revision_t youngest_opt_rev;
svn_revnum_t youngest_rev;
svn_revnum_t oldest_rev;
svn_opt_revision_t peg_rev;
svn_client__pathrev_t *ra_session_loc;
svn_client__pathrev_t *actual_loc;
apr_array_header_t *log_segments;
apr_array_header_t *revision_ranges;
@ -837,7 +839,7 @@ svn_client_log5(const apr_array_header_t *targets,
SVN_ERR(resolve_log_targets(&relative_targets, &ra_target, &peg_rev,
targets, ctx, pool, pool));
SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &actual_loc,
SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &ra_session_loc,
ra_target, NULL, &peg_rev, &peg_rev,
ctx, pool));
@ -851,11 +853,22 @@ svn_client_log5(const apr_array_header_t *targets,
opt_rev_ranges, &peg_rev,
ctx, pool, pool));
/* For some peg revisions we must resolve revision and url via a local path
so use the original RA_TARGET. For others, use the potentially corrected
(redirected) ra session URL. */
if (peg_rev.kind == svn_opt_revision_previous ||
peg_rev.kind == svn_opt_revision_base ||
peg_rev.kind == svn_opt_revision_committed ||
peg_rev.kind == svn_opt_revision_working)
path_or_url = ra_target;
else
path_or_url = ra_session_loc->url;
/* Make ACTUAL_LOC and RA_SESSION point to the youngest operative rev. */
youngest_opt_rev.kind = svn_opt_revision_number;
youngest_opt_rev.value.number = youngest_rev;
SVN_ERR(svn_client__resolve_rev_and_url(&actual_loc, ra_session,
ra_target, &peg_rev,
path_or_url, &peg_rev,
&youngest_opt_rev, ctx, pool));
SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
actual_loc->url, pool));

View File

@ -1258,13 +1258,14 @@ record_skip(merge_cmd_baton_t *merge_b,
svn_node_kind_t kind,
svn_wc_notify_action_t action,
svn_wc_notify_state_t state,
struct merge_dir_baton_t *pdb,
apr_pool_t *scratch_pool)
{
if (merge_b->record_only)
return SVN_NO_ERROR; /* ### Why? - Legacy compatibility */
if (merge_b->merge_source.ancestral
|| merge_b->reintegrate_merge)
if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
&& !(pdb && pdb->shadowed))
{
store_path(merge_b->skipped_abspaths, local_abspath);
}
@ -1979,7 +1980,8 @@ merge_file_changed(const char *relpath,
/* We haven't notified for this node yet: report a skip */
SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
svn_wc_notify_update_shadowed_update,
fb->skip_reason, scratch_pool));
fb->skip_reason, fb->parent_baton,
scratch_pool));
}
return SVN_NO_ERROR;
@ -2148,7 +2150,8 @@ merge_file_added(const char *relpath,
/* We haven't notified for this node yet: report a skip */
SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
svn_wc_notify_update_shadowed_add,
fb->skip_reason, scratch_pool));
fb->skip_reason, fb->parent_baton,
scratch_pool));
}
return SVN_NO_ERROR;
@ -2359,7 +2362,8 @@ merge_file_deleted(const char *relpath,
/* We haven't notified for this node yet: report a skip */
SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
svn_wc_notify_update_shadowed_delete,
fb->skip_reason, scratch_pool));
fb->skip_reason, fb->parent_baton,
scratch_pool));
}
return SVN_NO_ERROR;
@ -2723,6 +2727,12 @@ merge_dir_opened(void **new_dir_baton,
/* Set a tree conflict */
db->shadowed = TRUE;
db->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
&& !(pdb && pdb->shadowed))
{
store_path(merge_b->skipped_abspaths, local_abspath);
}
}
}
@ -2847,7 +2857,8 @@ merge_dir_changed(const char *relpath,
/* We haven't notified for this node yet: report a skip */
SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
svn_wc_notify_update_shadowed_update,
db->skip_reason, scratch_pool));
db->skip_reason, db->parent_baton,
scratch_pool));
}
return SVN_NO_ERROR;
@ -2931,7 +2942,8 @@ merge_dir_added(const char *relpath,
/* We haven't notified for this node yet: report a skip */
SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
svn_wc_notify_update_shadowed_add,
db->skip_reason, scratch_pool));
db->skip_reason, db->parent_baton,
scratch_pool));
}
return SVN_NO_ERROR;
@ -3098,7 +3110,8 @@ merge_dir_deleted(const char *relpath,
/* We haven't notified for this node yet: report a skip */
SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
svn_wc_notify_update_shadowed_delete,
db->skip_reason, scratch_pool));
db->skip_reason, db->parent_baton,
scratch_pool));
}
return SVN_NO_ERROR;
@ -3278,13 +3291,14 @@ merge_node_absent(const char *relpath,
apr_pool_t *scratch_pool)
{
merge_cmd_baton_t *merge_b = processor->baton;
struct merge_dir_baton_t *db = dir_baton;
const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
relpath, scratch_pool);
SVN_ERR(record_skip(merge_b, local_abspath, svn_node_unknown,
svn_wc_notify_skip, svn_wc_notify_state_missing,
scratch_pool));
db, scratch_pool));
return SVN_NO_ERROR;
}

View File

@ -2057,6 +2057,56 @@ send_patch_notification(const patch_target_t *target,
return SVN_NO_ERROR;
}
static void
svn_sort__array(apr_array_header_t *array,
int (*comparison_func)(const void *,
const void *))
{
qsort(array->elts, array->nelts, array->elt_size, comparison_func);
}
/* Implements the callback for svn_sort__array. Puts hunks that match
before hunks that do not match, puts hunks that match in order
based on postion matched, puts hunks that do not match in order
based on original position. */
static int
sort_matched_hunks(const void *a, const void *b)
{
const hunk_info_t *item1 = *((const hunk_info_t * const *)a);
const hunk_info_t *item2 = *((const hunk_info_t * const *)b);
svn_boolean_t matched1 = !item1->rejected && !item1->already_applied;
svn_boolean_t matched2 = !item2->rejected && !item2->already_applied;
svn_linenum_t original1, original2;
if (matched1 && matched2)
{
/* Both match so use order matched in file. */
if (item1->matched_line > item2->matched_line)
return 1;
else if (item1->matched_line == item2->matched_line)
return 0;
else
return -1;
}
else if (matched2)
/* Only second matches, put it before first. */
return 1;
else if (matched1)
/* Only first matches, put it before second. */
return -1;
/* Neither matches, sort by original_start. */
original1 = svn_diff_hunk_get_original_start(item1->hunk);
original2 = svn_diff_hunk_get_original_start(item2->hunk);
if (original1 > original2)
return 1;
else if (original1 == original2)
return 0;
else
return -1;
}
/* Apply a PATCH to a working copy at ABS_WC_PATH and put the result
* into temporary files, to be installed in the working copy later.
* Return information about the patch target in *PATCH_TARGET, allocated
@ -2138,6 +2188,10 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
APR_ARRAY_PUSH(target->content->hunks, hunk_info_t *) = hi;
}
/* Hunks are applied in the order determined by the matched line and
this may be different from the order of the original lines. */
svn_sort__array(target->content->hunks, sort_matched_hunks);
/* Apply or reject hunks. */
for (i = 0; i < target->content->hunks->nelts; i++)
{

View File

@ -82,6 +82,14 @@ fetch_repos_info(const char **repos_root,
return SVN_NO_ERROR;
}
/* Forward definition. Upgrades svn:externals properties in the working copy
LOCAL_ABSPATH to the WC-NG storage.
*/
static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
apr_pool_t *scratch_pool);
svn_error_t *
svn_client_upgrade(const char *path,
svn_client_ctx_t *ctx,
@ -89,10 +97,6 @@ svn_client_upgrade(const char *path,
{
const char *local_abspath;
apr_hash_t *externals;
apr_hash_index_t *hi;
apr_pool_t *iterpool;
apr_pool_t *iterpool2;
svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
struct repos_info_baton info_baton;
info_baton.state_pool = scratch_pool;
@ -111,6 +115,80 @@ svn_client_upgrade(const char *path,
ctx->notify_func2, ctx->notify_baton2,
scratch_pool));
SVN_ERR(svn_wc__externals_defined_below(&externals,
ctx->wc_ctx, local_abspath,
scratch_pool, scratch_pool));
if (apr_hash_count(externals) > 0)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_hash_index_t *hi;
/* We are upgrading from >= 1.7. No need to upgrade from
svn:externals properties. And by that avoiding the removal
of recorded externals information (issue #4519)
Only directory externals need an explicit upgrade */
for (hi = apr_hash_first(scratch_pool, externals);
hi;
hi = apr_hash_next(hi))
{
const char *ext_abspath;
svn_node_kind_t kind;
svn_pool_clear(iterpool);
ext_abspath = svn__apr_hash_index_key(hi);
SVN_ERR(svn_wc__read_external_info(&kind, NULL, NULL, NULL, NULL,
ctx->wc_ctx, local_abspath,
ext_abspath, FALSE,
iterpool, iterpool));
if (kind == svn_node_dir)
{
svn_error_t *err = svn_client_upgrade(ext_abspath, ctx, iterpool);
if (err)
{
svn_wc_notify_t *notify =
svn_wc_create_notify(ext_abspath,
svn_wc_notify_failed_external,
iterpool);
notify->err = err;
ctx->notify_func2(ctx->notify_baton2,
notify, iterpool);
svn_error_clear(err);
/* Next external node, please... */
}
}
}
svn_pool_destroy(iterpool);
}
else
{
/* Upgrading from <= 1.6, or no svn:properties defined.
(There is no way to detect the difference from libsvn_client :( ) */
SVN_ERR(upgrade_externals_from_properties(ctx, local_abspath,
scratch_pool));
}
return SVN_NO_ERROR;
}
static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
apr_pool_t *scratch_pool)
{
apr_hash_index_t *hi;
apr_pool_t *iterpool;
apr_pool_t *iterpool2;
apr_hash_t *externals;
svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
struct repos_info_baton info_baton;
/* Now it's time to upgrade the externals too. We do it after the wc
upgrade to avoid that errors in the externals causes the wc upgrade to
fail. Thanks to caching the performance penalty of walking the wc a
@ -163,7 +241,7 @@ svn_client_upgrade(const char *path,
iterpool);
if (!err)
err = svn_wc_parse_externals_description3(
&externals_p, svn_dirent_dirname(path, iterpool),
&externals_p, svn_dirent_dirname(local_abspath, iterpool),
external_desc->data, FALSE, iterpool);
if (err)
{

View File

@ -830,23 +830,23 @@ write_handler(void *baton,
p = decode_file_offset(&sview_offset, p, end);
if (p == NULL)
return SVN_NO_ERROR;
break;
p = decode_size(&sview_len, p, end);
if (p == NULL)
return SVN_NO_ERROR;
break;
p = decode_size(&tview_len, p, end);
if (p == NULL)
return SVN_NO_ERROR;
break;
p = decode_size(&inslen, p, end);
if (p == NULL)
return SVN_NO_ERROR;
break;
p = decode_size(&newlen, p, end);
if (p == NULL)
return SVN_NO_ERROR;
break;
if (tview_len > SVN_DELTA_WINDOW_SIZE ||
sview_len > SVN_DELTA_WINDOW_SIZE ||
@ -904,7 +904,15 @@ write_handler(void *baton,
db->subpool = newpool;
}
/* 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 that theoretical maximum
window header size. */
if (db->buffer->len > 5 * MAX_ENCODED_INT_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 */

View File

@ -1313,6 +1313,7 @@ svn_diff_parse_next_patch(svn_patch_t **patch,
line_after_tree_header_read = TRUE;
}
else if (! valid_header_line && state != state_start
&& state != state_git_diff_seen
&& !starts_with(line->data, "index "))
{
/* We've encountered an invalid diff header.

View File

@ -34,6 +34,7 @@
#include "svn_diff.h"
#include "svn_types.h"
#include "svn_ctype.h"
#include "svn_sorts.h"
#include "svn_utf.h"
#include "svn_version.h"
@ -486,23 +487,37 @@ display_mergeinfo_diff(const char *old_mergeinfo_val,
return SVN_NO_ERROR;
}
/* qsort callback handling svn_prop_t by name */
static int
propchange_sort(const void *k1, const void *k2)
{
const svn_prop_t *propchange1 = k1;
const svn_prop_t *propchange2 = k2;
return strcmp(propchange1->name, propchange2->name);
}
svn_error_t *
svn_diff__display_prop_diffs(svn_stream_t *outstream,
const char *encoding,
const apr_array_header_t *propchanges,
apr_hash_t *original_props,
svn_boolean_t pretty_print_mergeinfo,
apr_pool_t *pool)
apr_pool_t *scratch_pool)
{
apr_pool_t *pool = scratch_pool;
apr_pool_t *iterpool = svn_pool_create(pool);
apr_array_header_t *changes = apr_array_copy(scratch_pool, propchanges);
int i;
for (i = 0; i < propchanges->nelts; i++)
qsort(changes->elts, changes->nelts, changes->elt_size, propchange_sort);
for (i = 0; i < changes->nelts; i++)
{
const char *action;
const svn_string_t *original_value;
const svn_prop_t *propchange
= &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
= &APR_ARRAY_IDX(changes, i, svn_prop_t);
if (original_props)
original_value = svn_hash_gets(original_props, propchange->name);

View File

@ -89,7 +89,7 @@ read_config(svn_memcache_t **memcache_p,
fs_fs_data_t *ffd = fs->fsap_data;
SVN_ERR(svn_cache__make_memcache_from_config(memcache_p, ffd->config,
fs->pool));
fs->pool));
/* No cache namespace by default. I.e. all FS instances share the
* cached data. If you specify different namespaces, the data will
@ -129,23 +129,9 @@ read_config(svn_memcache_t **memcache_p,
SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
TRUE);
/* don't cache revprops by default.
* Revprop caching significantly speeds up operations like
* svn ls -v. However, it requires synchronization that may
* not be available or efficient in the current server setup.
*
* If the caller chose option "2", enable revprop caching if
* the required API support is there to make it efficient.
/* For now, always disable revprop caching.
*/
if (strcmp(svn_hash__get_cstring(fs->config,
SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
""), "2"))
*cache_revprops
= svn_hash__get_bool(fs->config,
SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
FALSE);
else
*cache_revprops = svn_named_atomic__is_efficient();
*cache_revprops = FALSE;
return svn_config_get_bool(ffd->config, fail_stop,
CONFIG_SECTION_CACHES, CONFIG_OPTION_FAIL_STOP,

View File

@ -3988,17 +3988,23 @@ write_non_packed_revprop(const char **final_path,
apr_hash_t *proplist,
apr_pool_t *pool)
{
apr_file_t *file;
svn_stream_t *stream;
*final_path = path_revprops(fs, rev, pool);
/* ### do we have a directory sitting around already? we really shouldn't
### have to get the dirname here. */
SVN_ERR(svn_stream_open_unique(&stream, tmp_path,
svn_dirent_dirname(*final_path, pool),
svn_io_file_del_none, pool, pool));
SVN_ERR(svn_io_open_unique_file3(&file, tmp_path,
svn_dirent_dirname(*final_path, pool),
svn_io_file_del_none, pool, pool));
stream = svn_stream_from_aprfile2(file, TRUE, pool);
SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR, pool));
SVN_ERR(svn_stream_close(stream));
/* Flush temporary file to disk and close it. */
SVN_ERR(svn_io_file_flush_to_disk(file, pool));
SVN_ERR(svn_io_file_close(file, pool));
return SVN_NO_ERROR;
}
@ -4085,7 +4091,7 @@ serialize_revprops_header(svn_stream_t *stream,
return SVN_NO_ERROR;
}
/* Writes the a pack file to FILE_STREAM. It copies the serialized data
/* Writes the a pack file to FILE. It copies the serialized data
* from REVPROPS for the indexes [START,END) except for index CHANGED_INDEX.
*
* The data for the latter is taken from NEW_SERIALIZED. Note, that
@ -4103,7 +4109,7 @@ repack_revprops(svn_fs_t *fs,
int changed_index,
svn_stringbuf_t *new_serialized,
apr_off_t new_total_size,
svn_stream_t *file_stream,
apr_file_t *file,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
@ -4151,9 +4157,11 @@ repack_revprops(svn_fs_t *fs,
? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT
: SVN_DELTA_COMPRESSION_LEVEL_NONE));
/* finally, write the content to the target stream and close it */
SVN_ERR(svn_stream_write(file_stream, compressed->data, &compressed->len));
SVN_ERR(svn_stream_close(file_stream));
/* finally, write the content to the target file, flush and close it */
SVN_ERR(svn_io_file_write_full(file, compressed->data, compressed->len,
NULL, pool));
SVN_ERR(svn_io_file_flush_to_disk(file, pool));
SVN_ERR(svn_io_file_close(file, pool));
return SVN_NO_ERROR;
}
@ -4161,23 +4169,22 @@ repack_revprops(svn_fs_t *fs,
/* Allocate a new pack file name for revisions
* [REVPROPS->START_REVISION + START, REVPROPS->START_REVISION + END - 1]
* of REVPROPS->MANIFEST. Add the name of old file to FILES_TO_DELETE,
* auto-create that array if necessary. Return an open file stream to
* the new file in *STREAM allocated in POOL.
* auto-create that array if necessary. Return an open file *FILE that is
* allocated in POOL.
*/
static svn_error_t *
repack_stream_open(svn_stream_t **stream,
svn_fs_t *fs,
packed_revprops_t *revprops,
int start,
int end,
apr_array_header_t **files_to_delete,
apr_pool_t *pool)
repack_file_open(apr_file_t **file,
svn_fs_t *fs,
packed_revprops_t *revprops,
int start,
int end,
apr_array_header_t **files_to_delete,
apr_pool_t *pool)
{
apr_int64_t tag;
const char *tag_string;
svn_string_t *new_filename;
int i;
apr_file_t *file;
int manifest_offset
= (int)(revprops->start_revision - revprops->manifest_start);
@ -4209,12 +4216,11 @@ repack_stream_open(svn_stream_t **stream,
APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*)
= new_filename->data;
/* create a file stream for the new file */
SVN_ERR(svn_io_file_open(&file, svn_dirent_join(revprops->folder,
new_filename->data,
pool),
/* open the file */
SVN_ERR(svn_io_file_open(file, svn_dirent_join(revprops->folder,
new_filename->data,
pool),
APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool));
*stream = svn_stream_from_aprfile2(file, FALSE, pool);
return SVN_NO_ERROR;
}
@ -4238,6 +4244,7 @@ write_packed_revprop(const char **final_path,
packed_revprops_t *revprops;
apr_int64_t generation = 0;
svn_stream_t *stream;
apr_file_t *file;
svn_stringbuf_t *serialized;
apr_off_t new_total_size;
int changed_index;
@ -4273,11 +4280,11 @@ write_packed_revprop(const char **final_path,
*final_path = svn_dirent_join(revprops->folder, revprops->filename,
pool);
SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder,
svn_io_file_del_none, pool, pool));
SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder,
svn_io_file_del_none, pool, pool));
SVN_ERR(repack_revprops(fs, revprops, 0, revprops->sizes->nelts,
changed_index, serialized, new_total_size,
stream, pool));
file, pool));
}
else
{
@ -4323,50 +4330,53 @@ write_packed_revprop(const char **final_path,
/* write the new, split files */
if (left_count)
{
SVN_ERR(repack_stream_open(&stream, fs, revprops, 0,
left_count, files_to_delete, pool));
SVN_ERR(repack_file_open(&file, fs, revprops, 0,
left_count, files_to_delete, pool));
SVN_ERR(repack_revprops(fs, revprops, 0, left_count,
changed_index, serialized, new_total_size,
stream, pool));
file, pool));
}
if (left_count + right_count < revprops->sizes->nelts)
{
SVN_ERR(repack_stream_open(&stream, fs, revprops, changed_index,
changed_index + 1, files_to_delete,
pool));
SVN_ERR(repack_file_open(&file, fs, revprops, changed_index,
changed_index + 1, files_to_delete,
pool));
SVN_ERR(repack_revprops(fs, revprops, changed_index,
changed_index + 1,
changed_index, serialized, new_total_size,
stream, pool));
file, pool));
}
if (right_count)
{
SVN_ERR(repack_stream_open(&stream, fs, revprops,
revprops->sizes->nelts - right_count,
revprops->sizes->nelts,
files_to_delete, pool));
SVN_ERR(repack_file_open(&file, fs, revprops,
revprops->sizes->nelts - right_count,
revprops->sizes->nelts,
files_to_delete, pool));
SVN_ERR(repack_revprops(fs, revprops,
revprops->sizes->nelts - right_count,
revprops->sizes->nelts, changed_index,
serialized, new_total_size, stream,
serialized, new_total_size, file,
pool));
}
/* write the new manifest */
*final_path = svn_dirent_join(revprops->folder, PATH_MANIFEST, pool);
SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder,
svn_io_file_del_none, pool, pool));
SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder,
svn_io_file_del_none, pool, pool));
for (i = 0; i < revprops->manifest->nelts; ++i)
{
const char *filename = APR_ARRAY_IDX(revprops->manifest, i,
const char*);
SVN_ERR(svn_stream_printf(stream, pool, "%s\n", filename));
SVN_ERR(svn_io_file_write_full(file, filename, strlen(filename),
NULL, pool));
SVN_ERR(svn_io_file_putc('\n', file, pool));
}
SVN_ERR(svn_stream_close(stream));
SVN_ERR(svn_io_file_flush_to_disk(file, pool));
SVN_ERR(svn_io_file_close(file, pool));
}
return SVN_NO_ERROR;
@ -5062,9 +5072,11 @@ get_combined_window(svn_stringbuf_t **result,
/* Maybe, we've got a PLAIN start representation. If we do, read
as much data from it as the needed for the txdelta window's source
view.
Note that BUF / SOURCE may only be NULL in the first iteration. */
Note that BUF / SOURCE may only be NULL in the first iteration.
Also note that we may have short-cut reading the delta chain --
in which case SRC_OPS is 0 and it might not be a PLAIN rep. */
source = buf;
if (source == NULL && rb->src_state != NULL)
if (source == NULL && rb->src_state != NULL && window->src_ops)
SVN_ERR(read_plain_window(&source, rb->src_state, window->sview_len,
pool));
@ -6966,8 +6978,13 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
rep = apr_pcalloc(pool, sizeof(*rep));
rep->revision = SVN_INVALID_REVNUM;
rep->txn_id = txn_id;
SVN_ERR(get_new_txn_node_id(&unique_suffix, fs, txn_id, pool));
rep->uniquifier = apr_psprintf(pool, "%s/%s", txn_id, unique_suffix);
if (ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT)
{
SVN_ERR(get_new_txn_node_id(&unique_suffix, fs, txn_id, pool));
rep->uniquifier = apr_psprintf(pool, "%s/%s", txn_id, unique_suffix);
}
parent_noderev->data_rep = rep;
SVN_ERR(svn_fs_fs__put_node_revision(fs, parent_noderev->id,
parent_noderev, FALSE, pool));
@ -7551,6 +7568,7 @@ rep_write_contents_close(void *baton)
representation_t *rep;
representation_t *old_rep;
apr_off_t offset;
fs_fs_data_t *ffd = b->fs->fsap_data;
rep = apr_pcalloc(b->parent_pool, sizeof(*rep));
rep->offset = b->rep_offset;
@ -7567,9 +7585,13 @@ rep_write_contents_close(void *baton)
/* Fill in the rest of the representation field. */
rep->expanded_size = b->rep_size;
rep->txn_id = svn_fs_fs__id_txn_id(b->noderev->id);
SVN_ERR(get_new_txn_node_id(&unique_suffix, b->fs, rep->txn_id, b->pool));
rep->uniquifier = apr_psprintf(b->parent_pool, "%s/%s", rep->txn_id,
unique_suffix);
if (ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT)
{
SVN_ERR(get_new_txn_node_id(&unique_suffix, b->fs, rep->txn_id, b->pool));
rep->uniquifier = apr_psprintf(b->parent_pool, "%s/%s", rep->txn_id,
unique_suffix);
}
rep->revision = SVN_INVALID_REVNUM;
/* Finalize the checksum. */
@ -7842,7 +7864,7 @@ write_hash_rep(representation_t *rep,
/* update the representation */
rep->size = whb->size;
rep->expanded_size = 0;
rep->expanded_size = whb->size;
}
return SVN_NO_ERROR;
@ -9070,7 +9092,9 @@ recover_find_max_ids(svn_fs_t *fs, svn_revnum_t rev,
stored in the representation. */
baton.file = rev_file;
baton.pool = pool;
baton.remaining = data_rep->expanded_size;
baton.remaining = data_rep->expanded_size
? data_rep->expanded_size
: data_rep->size;
stream = svn_stream_create(&baton, pool);
svn_stream_set_read(stream, read_handler_recover);
@ -10912,6 +10936,9 @@ hotcopy_update_current(svn_revnum_t *dst_youngest,
{
apr_off_t root_offset;
apr_file_t *rev_file;
char max_node_id[MAX_KEY_SIZE] = "0";
char max_copy_id[MAX_KEY_SIZE] = "0";
apr_size_t len;
if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
SVN_ERR(update_min_unpacked_rev(dst_fs, scratch_pool));
@ -10921,9 +10948,15 @@ hotcopy_update_current(svn_revnum_t *dst_youngest,
SVN_ERR(get_root_changes_offset(&root_offset, NULL, rev_file,
dst_fs, new_youngest, scratch_pool));
SVN_ERR(recover_find_max_ids(dst_fs, new_youngest, rev_file,
root_offset, next_node_id, next_copy_id,
root_offset, max_node_id, max_copy_id,
scratch_pool));
SVN_ERR(svn_io_file_close(rev_file, scratch_pool));
/* We store the _next_ ids. */
len = strlen(max_node_id);
svn_fs_fs__next_key(max_node_id, &len, next_node_id);
len = strlen(max_copy_id);
svn_fs_fs__next_key(max_copy_id, &len, next_copy_id);
}
/* Update 'current'. */

View File

@ -1,4 +1,4 @@
/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.8.10/subversion/libsvn_fs_fs/token-map.h.
/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.8.14/subversion/libsvn_fs_fs/token-map.h.
* Do not edit this file -- edit the source and rerun gen-make.py */
#define STMT_CREATE_SCHEMA 0

View File

@ -127,7 +127,6 @@ typedef struct fs_txn_root_data_t
static svn_error_t * get_dag(dag_node_t **dag_node_p,
svn_fs_root_t *root,
const char *path,
svn_boolean_t needs_lock_cache,
apr_pool_t *pool);
static svn_fs_root_t *make_revision_root(svn_fs_t *fs, svn_revnum_t rev,
@ -178,34 +177,10 @@ typedef struct cache_entry_t
*/
enum { BUCKET_COUNT = 256 };
/* Each pool that has received a DAG node, will hold at least on lock on
our cache to ensure that the node remains valid despite being allocated
in the cache's pool. This is the structure to represent the lock.
*/
typedef struct cache_lock_t
{
/* pool holding the lock */
apr_pool_t *pool;
/* cache being locked */
fs_fs_dag_cache_t *cache;
/* next lock. NULL at EOL */
struct cache_lock_t *next;
/* previous lock. NULL at list head. Only then this==cache->first_lock */
struct cache_lock_t *prev;
} cache_lock_t;
/* The actual cache structure. All nodes will be allocated in POOL.
When the number of INSERTIONS (i.e. objects created form that pool)
exceeds a certain threshold, the pool will be cleared and the cache
with it.
To ensure that nodes returned from this structure remain valid, the
cache will get locked for the lifetime of the _receiving_ pools (i.e.
those in which we would allocate the node if there was no cache.).
The cache will only be cleared FIRST_LOCK is 0.
*/
struct fs_fs_dag_cache_t
{
@ -221,106 +196,23 @@ struct fs_fs_dag_cache_t
/* Property lookups etc. have a very high locality (75% re-hit).
Thus, remember the last hit location for optimistic lookup. */
apr_size_t last_hit;
/* List of receiving pools that are still alive. */
cache_lock_t *first_lock;
};
/* Cleanup function to be called when a receiving pool gets cleared.
Unlocks the cache once.
*/
static apr_status_t
unlock_cache(void *baton_void)
{
cache_lock_t *lock = baton_void;
/* remove lock from chain. Update the head */
if (lock->next)
lock->next->prev = lock->prev;
if (lock->prev)
lock->prev->next = lock->next;
else
lock->cache->first_lock = lock->next;
return APR_SUCCESS;
}
/* Cleanup function to be called when the cache itself gets destroyed.
In that case, we must unregister all unlock requests.
*/
static apr_status_t
unregister_locks(void *baton_void)
{
fs_fs_dag_cache_t *cache = baton_void;
cache_lock_t *lock;
for (lock = cache->first_lock; lock; lock = lock->next)
apr_pool_cleanup_kill(lock->pool,
lock,
unlock_cache);
return APR_SUCCESS;
}
fs_fs_dag_cache_t*
svn_fs_fs__create_dag_cache(apr_pool_t *pool)
{
fs_fs_dag_cache_t *result = apr_pcalloc(pool, sizeof(*result));
result->pool = svn_pool_create(pool);
apr_pool_cleanup_register(pool,
result,
unregister_locks,
apr_pool_cleanup_null);
return result;
}
/* Prevent the entries in CACHE from being destroyed, for as long as the
POOL lives.
*/
static void
lock_cache(fs_fs_dag_cache_t* cache, apr_pool_t *pool)
{
/* we only need to lock / unlock once per pool. Since we will often ask
for multiple nodes with the same pool, we can reduce the overhead.
However, if e.g. pools are being used in an alternating pattern,
we may lock the cache more than once for the same pool (and register
just as many cleanup actions).
*/
cache_lock_t *lock = cache->first_lock;
/* try to find an existing lock for POOL.
But limit the time spent on chasing pointers. */
int limiter = 8;
while (lock && --limiter)
if (lock->pool == pool)
return;
/* create a new lock and put it at the beginning of the lock chain */
lock = apr_palloc(pool, sizeof(*lock));
lock->cache = cache;
lock->pool = pool;
lock->next = cache->first_lock;
lock->prev = NULL;
if (cache->first_lock)
cache->first_lock->prev = lock;
cache->first_lock = lock;
/* instruct POOL to remove the look upon cleanup */
apr_pool_cleanup_register(pool,
lock,
unlock_cache,
apr_pool_cleanup_null);
}
/* Clears the CACHE at regular intervals (destroying all cached nodes)
*/
static void
auto_clear_dag_cache(fs_fs_dag_cache_t* cache)
{
if (cache->first_lock == NULL && cache->insertions > BUCKET_COUNT)
if (cache->insertions > BUCKET_COUNT)
{
svn_pool_clear(cache->pool);
@ -433,18 +325,12 @@ locate_cache(svn_cache__t **cache,
}
}
/* Return NODE for PATH from ROOT's node cache, or NULL if the node
isn't cached; read it from the FS. *NODE remains valid until either
POOL or the FS gets cleared or destroyed (whichever comes first).
Since locking can be expensive and POOL may be long-living, for
nodes that will not need to survive the next call to this function,
set NEEDS_LOCK_CACHE to FALSE. */
/* Return NODE_P for PATH from ROOT's node cache, or NULL if the node
isn't cached; read it from the FS. *NODE_P is allocated in POOL. */
static svn_error_t *
dag_node_cache_get(dag_node_t **node_p,
svn_fs_root_t *root,
const char *path,
svn_boolean_t needs_lock_cache,
apr_pool_t *pool)
{
svn_boolean_t found;
@ -466,25 +352,23 @@ dag_node_cache_get(dag_node_t **node_p,
if (bucket->node == NULL)
{
locate_cache(&cache, &key, root, path, pool);
SVN_ERR(svn_cache__get((void **)&node, &found, cache, key,
ffd->dag_node_cache->pool));
SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, pool));
if (found && node)
{
/* Patch up the FS, since this might have come from an old FS
* object. */
svn_fs_fs__dag_set_fs(node, root->fs);
bucket->node = node;
/* Retain the DAG node in L1 cache. */
bucket->node = svn_fs_fs__dag_dup(node,
ffd->dag_node_cache->pool);
}
}
else
{
node = bucket->node;
/* Copy the node from L1 cache into the passed-in POOL. */
node = svn_fs_fs__dag_dup(bucket->node, pool);
}
/* if we found a node, make sure it remains valid at least as long
as it would when allocated in POOL. */
if (node && needs_lock_cache)
lock_cache(ffd->dag_node_cache, pool);
}
else
{
@ -822,7 +706,7 @@ get_copy_inheritance(copy_id_inherit_t *inherit_p,
SVN_ERR(svn_fs_fs__dag_get_copyroot(&copyroot_rev, &copyroot_path,
child->node));
SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, fs, copyroot_rev, pool));
SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, FALSE, pool));
SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
if (svn_fs_fs__id_compare(copyroot_id, child_id) == -1)
@ -938,7 +822,7 @@ open_path(parent_path_t **parent_path_p,
{
directory = svn_dirent_dirname(path, pool);
if (directory[1] != 0) /* root nodes are covered anyway */
SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool));
SVN_ERR(dag_node_cache_get(&here, root, directory, pool));
}
/* did the shortcut work? */
@ -998,8 +882,8 @@ open_path(parent_path_t **parent_path_p,
element if we already know the lookup to fail for the
complete path. */
if (next || !(flags & open_path_uncached))
SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far,
TRUE, pool));
SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, pool));
if (cached_node)
child = cached_node;
else
@ -1136,8 +1020,7 @@ make_path_mutable(svn_fs_root_t *root,
parent_path->node));
SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, root->fs,
copyroot_rev, pool));
SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path,
FALSE, pool));
SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
child_id = svn_fs_fs__dag_get_id(parent_path->node);
copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
@ -1174,16 +1057,11 @@ make_path_mutable(svn_fs_root_t *root,
/* Open the node identified by PATH in ROOT. Set DAG_NODE_P to the
node we find, allocated in POOL. Return the error
SVN_ERR_FS_NOT_FOUND if this node doesn't exist.
Since locking can be expensive and POOL may be long-living, for
nodes that will not need to survive the next call to this function,
set NEEDS_LOCK_CACHE to FALSE. */
SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */
static svn_error_t *
get_dag(dag_node_t **dag_node_p,
svn_fs_root_t *root,
const char *path,
svn_boolean_t needs_lock_cache,
apr_pool_t *pool)
{
parent_path_t *parent_path;
@ -1192,7 +1070,7 @@ get_dag(dag_node_t **dag_node_p,
/* First we look for the DAG in our cache
(if the path may be canonical). */
if (*path == '/')
SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, pool));
SVN_ERR(dag_node_cache_get(&node, root, path, pool));
if (! node)
{
@ -1202,8 +1080,7 @@ get_dag(dag_node_t **dag_node_p,
path = svn_fs__canonicalize_abspath(path, pool);
/* Try again with the corrected path. */
SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache,
pool));
SVN_ERR(dag_node_cache_get(&node, root, path, pool));
}
if (! node)
@ -1281,7 +1158,7 @@ svn_fs_fs__node_id(const svn_fs_id_t **id_p,
{
dag_node_t *node;
SVN_ERR(get_dag(&node, root, path, FALSE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
*id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(node), pool);
}
return SVN_NO_ERROR;
@ -1296,7 +1173,7 @@ svn_fs_fs__node_created_rev(svn_revnum_t *revision,
{
dag_node_t *node;
SVN_ERR(get_dag(&node, root, path, FALSE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
return svn_fs_fs__dag_get_revision(revision, node, pool);
}
@ -1311,7 +1188,7 @@ fs_node_created_path(const char **created_path,
{
dag_node_t *node;
SVN_ERR(get_dag(&node, root, path, TRUE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
*created_path = svn_fs_fs__dag_get_created_path(node);
return SVN_NO_ERROR;
@ -1375,7 +1252,7 @@ fs_node_prop(svn_string_t **value_p,
dag_node_t *node;
apr_hash_t *proplist;
SVN_ERR(get_dag(&node, root, path, FALSE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, node, pool));
*value_p = NULL;
if (proplist)
@ -1398,7 +1275,7 @@ fs_node_proplist(apr_hash_t **table_p,
apr_hash_t *table;
dag_node_t *node;
SVN_ERR(get_dag(&node, root, path, FALSE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
SVN_ERR(svn_fs_fs__dag_get_proplist(&table, node, pool));
*table_p = table ? table : apr_hash_make(pool);
@ -1515,8 +1392,8 @@ fs_props_changed(svn_boolean_t *changed_p,
(SVN_ERR_FS_GENERAL, NULL,
_("Cannot compare property value between two different filesystems"));
SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
SVN_ERR(get_dag(&node1, root1, path1, pool));
SVN_ERR(get_dag(&node2, root2, path2, pool));
return svn_fs_fs__dag_things_different(changed_p, NULL,
node1, node2);
}
@ -1529,7 +1406,7 @@ fs_props_changed(svn_boolean_t *changed_p,
static svn_error_t *
get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool)
{
return get_dag(node, root, "/", TRUE, pool);
return get_dag(node, root, "/", pool);
}
@ -2193,7 +2070,7 @@ fs_dir_entries(apr_hash_t **table_p,
dag_node_t *node;
/* Get the entries for this path in the caller's pool. */
SVN_ERR(get_dag(&node, root, path, FALSE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
return svn_fs_fs__dag_dir_entries(table_p, node, pool);
}
@ -2365,7 +2242,7 @@ copy_helper(svn_fs_root_t *from_root,
_("Copy from mutable tree not currently supported"));
/* Get the NODE for FROM_PATH in FROM_ROOT.*/
SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool));
SVN_ERR(get_dag(&from_node, from_root, from_path, pool));
/* Build up the parent path from TO_PATH in TO_ROOT. If the last
component does not exist, it's not that big a deal. We'll just
@ -2442,7 +2319,7 @@ copy_helper(svn_fs_root_t *from_root,
pool));
/* Make a record of this modification in the changes table. */
SVN_ERR(get_dag(&new_node, to_root, to_path, TRUE, pool));
SVN_ERR(get_dag(&new_node, to_root, to_path, pool));
SVN_ERR(add_change(to_root->fs, txn_id, to_path,
svn_fs_fs__dag_get_id(new_node), kind, FALSE, FALSE,
svn_fs_fs__dag_node_kind(from_node),
@ -2553,7 +2430,7 @@ fs_copied_from(svn_revnum_t *rev_p,
{
/* There is no cached entry, look it up the old-fashioned
way. */
SVN_ERR(get_dag(&node, root, path, TRUE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&copyfrom_rev, node));
SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copyfrom_path, node));
}
@ -2628,7 +2505,7 @@ fs_file_length(svn_filesize_t *length_p,
dag_node_t *file;
/* First create a dag_node_t from the root/path pair. */
SVN_ERR(get_dag(&file, root, path, FALSE, pool));
SVN_ERR(get_dag(&file, root, path, pool));
/* Now fetch its length */
return svn_fs_fs__dag_file_length(length_p, file, pool);
@ -2647,7 +2524,7 @@ fs_file_checksum(svn_checksum_t **checksum,
{
dag_node_t *file;
SVN_ERR(get_dag(&file, root, path, FALSE, pool));
SVN_ERR(get_dag(&file, root, path, pool));
return svn_fs_fs__dag_file_checksum(checksum, file, kind, pool);
}
@ -2666,7 +2543,7 @@ fs_file_contents(svn_stream_t **contents,
svn_stream_t *file_stream;
/* First create a dag_node_t from the root/path pair. */
SVN_ERR(get_dag(&node, root, path, FALSE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
/* Then create a readable stream from the dag_node_t. */
SVN_ERR(svn_fs_fs__dag_get_contents(&file_stream, node, pool));
@ -2689,7 +2566,7 @@ fs_try_process_file_contents(svn_boolean_t *success,
apr_pool_t *pool)
{
dag_node_t *node;
SVN_ERR(get_dag(&node, root, path, FALSE, pool));
SVN_ERR(get_dag(&node, root, path, pool));
return svn_fs_fs__dag_try_process_file_contents(success, node,
processor, baton, pool);
@ -3071,8 +2948,8 @@ fs_contents_changed(svn_boolean_t *changed_p,
(SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2);
}
SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
SVN_ERR(get_dag(&node1, root1, path1, pool));
SVN_ERR(get_dag(&node2, root2, path2, pool));
return svn_fs_fs__dag_things_different(NULL, changed_p,
node1, node2);
}
@ -3092,10 +2969,10 @@ fs_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
dag_node_t *source_node, *target_node;
if (source_root && source_path)
SVN_ERR(get_dag(&source_node, source_root, source_path, TRUE, pool));
SVN_ERR(get_dag(&source_node, source_root, source_path, pool));
else
source_node = NULL;
SVN_ERR(get_dag(&target_node, target_root, target_path, TRUE, pool));
SVN_ERR(get_dag(&target_node, target_root, target_path, pool));
/* Create a delta stream that turns the source into the target. */
return svn_fs_fs__dag_get_file_delta_stream(stream_p, source_node,
@ -3588,7 +3465,7 @@ history_prev(void *baton, apr_pool_t *pool)
SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, fs, copyroot_rev,
pool));
SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, FALSE, pool));
SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, pool));
copy_dst = svn_fs_fs__dag_get_created_path(node);
/* If our current path was the very destination of the copy,
@ -3785,7 +3662,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root,
svn_pool_clear(iterpool);
kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
SVN_ERR(get_dag(&kid_dag, root, kid_path, TRUE, iterpool));
SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag));
SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag));
@ -4031,7 +3908,7 @@ add_descendant_mergeinfo(svn_mergeinfo_catalog_t result_catalog,
dag_node_t *this_dag;
svn_boolean_t go_down;
SVN_ERR(get_dag(&this_dag, root, path, TRUE, scratch_pool));
SVN_ERR(get_dag(&this_dag, root, path, scratch_pool));
SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down,
this_dag));
if (go_down)

View File

@ -2234,6 +2234,7 @@ close_edit(void *edit_baton,
ctx->activity_url ? ctx->activity_url : ctx->txn_url;
const svn_commit_info_t *commit_info;
int response_code;
svn_error_t *err = NULL;
/* MERGE our activity */
SVN_ERR(svn_ra_serf__run_merge(&commit_info, &response_code,
@ -2252,9 +2253,11 @@ close_edit(void *edit_baton,
response_code);
}
ctx->txn_url = NULL; /* If HTTPv2, the txn is now done */
/* Inform the WC that we did a commit. */
if (ctx->callback)
SVN_ERR(ctx->callback(commit_info, ctx->callback_baton, pool));
err = ctx->callback(commit_info, ctx->callback_baton, pool);
/* If we're using activities, DELETE our completed activity. */
if (ctx->activity_url)
@ -2271,11 +2274,17 @@ close_edit(void *edit_baton,
handler->response_handler = svn_ra_serf__expect_empty_body;
handler->response_baton = handler;
SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
ctx->activity_url = NULL; /* Don't try again in abort_edit() on fail */
SVN_ERR(svn_error_compose_create(
err,
svn_ra_serf__context_run_one(handler, pool)));
SVN_ERR_ASSERT(handler->sline.code == 204);
}
SVN_ERR(err);
return SVN_NO_ERROR;
}

View File

@ -33,6 +33,7 @@
#include "svn_ra.h"
#include "svn_dav.h"
#include "svn_xml.h"
#include "svn_ctype.h"
#include "../libsvn_ra/ra_loader.h"
#include "svn_private_config.h"
@ -227,7 +228,9 @@ capabilities_headers_iterator_callback(void *baton,
}
/* SVN-specific headers -- if present, server supports HTTP protocol v2 */
else if (strncmp(key, "SVN", 3) == 0)
else if (!svn_ctype_casecmp(key[0], 'S')
&& !svn_ctype_casecmp(key[1], 'V')
&& !svn_ctype_casecmp(key[2], 'N'))
{
/* If we've not yet seen any information about supported POST
requests, we'll initialize the list/hash with "create-txn"

View File

@ -777,6 +777,13 @@ close_edit(void *edit_baton,
post_commit_err = svn_repos__post_commit_error_str(err, pool);
svn_error_clear(err);
}
/* Make sure a future abort doesn't perform
any work. This may occur if the commit
callback returns an error! */
eb->txn = NULL;
eb->txn_root = NULL;
}
else
{

View File

@ -40,6 +40,7 @@
#include <apr_lib.h>
#include "private/svn_repos_private.h"
#include "private/svn_fspath.h"
#include "private/svn_dep_compat.h"
#include "private/svn_mergeinfo_private.h"
@ -61,7 +62,7 @@ struct parse_baton
const char *parent_dir; /* repository relpath, or NULL */
svn_repos_notify_func_t notify_func;
void *notify_baton;
svn_repos_notify_t *notify;
apr_pool_t *notify_pool; /* scratch pool for notifications */
apr_pool_t *pool;
/* Start and end (inclusive) of revision range we'll pay attention
@ -329,16 +330,7 @@ renumber_mergeinfo_revs(svn_string_t **final_val,
SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
subpool, subpool));
SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
/* Mergeinfo revision sources for r0 and r1 are invalid; you can't merge r0
or r1. However, svndumpfilter can be abused to produce r1 merge source
revs. So if we encounter any, then strip them out, no need to put them
into the load target. */
SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&final_mergeinfo,
final_mergeinfo,
1, 0, FALSE,
subpool, subpool));
SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
svn_pool_destroy(subpool);
@ -502,9 +494,14 @@ new_revision_record(void **revision_baton,
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_txn_start;
pb->notify->old_revision = rb->rev;
pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
/* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_load_txn_start,
pb->notify_pool);
notify->old_revision = rb->rev;
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
/* Stash the oldest "old" revision committed from the load stream. */
@ -515,9 +512,14 @@ new_revision_record(void **revision_baton,
/* If we're skipping this revision, try to notify someone. */
if (rb->skipped && pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_skipped_rev;
pb->notify->old_revision = rb->rev;
pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
/* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_load_skipped_rev,
pb->notify_pool);
notify->old_revision = rb->rev;
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
/* If we're parsing revision 0, only the revision are (possibly)
@ -586,8 +588,13 @@ maybe_add_with_history(struct node_baton *nb,
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_copied_node;
pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
/* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_load_copied_node,
pb->notify_pool);
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
}
@ -656,10 +663,14 @@ new_node_record(void **node_baton,
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_node_start;
pb->notify->node_action = nb->action;
pb->notify->path = nb->path;
pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
/* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_load_node_start,
pb->notify_pool);
notify->path = nb->path;
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
switch (nb->action)
@ -726,6 +737,67 @@ set_revision_property(void *baton,
}
/* Adjust mergeinfo:
* - normalize line endings (if all CRLF, change to LF; but error if mixed);
* - adjust revision numbers (see renumber_mergeinfo_revs());
* - adjust paths (see prefix_mergeinfo_paths()).
*/
static svn_error_t *
adjust_mergeinfo_property(struct revision_baton *rb,
svn_string_t **new_value_p,
const svn_string_t *old_value,
apr_pool_t *result_pool)
{
struct parse_baton *pb = rb->pb;
svn_string_t prop_val = *old_value;
/* Tolerate mergeinfo with "\r\n" line endings because some
dumpstream sources might contain as much. If so normalize
the line endings to '\n' and make a notification to
PARSE_BATON->FEEDBACK_STREAM that we have made this
correction. */
if (strstr(prop_val.data, "\r"))
{
const char *prop_eol_normalized;
SVN_ERR(svn_subst_translate_cstring2(prop_val.data,
&prop_eol_normalized,
"\n", /* translate to LF */
FALSE, /* no repair */
NULL, /* no keywords */
FALSE, /* no expansion */
result_pool));
prop_val.data = prop_eol_normalized;
prop_val.len = strlen(prop_eol_normalized);
if (pb->notify_func)
{
/* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify
= svn_repos_notify_create(
svn_repos_notify_load_normalized_mergeinfo,
pb->notify_pool);
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
}
/* Renumber mergeinfo as appropriate. */
SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val, rb,
result_pool));
if (pb->parent_dir)
{
/* Prefix the merge source paths with PB->parent_dir. */
/* ASSUMPTION: All source paths are included in the dump stream. */
SVN_ERR(prefix_mergeinfo_paths(new_value_p, *new_value_p,
pb->parent_dir, result_pool));
}
return SVN_NO_ERROR;
}
static svn_error_t *
set_node_property(void *baton,
const char *name,
@ -739,51 +811,42 @@ set_node_property(void *baton,
if (rb->skipped)
return SVN_NO_ERROR;
/* Adjust mergeinfo. If this fails, presumably because the mergeinfo
property has an ill-formed value, then we must not fail to load
the repository (at least if it's a simple load with no revision
offset adjustments, path changes, etc.) so just warn and leave it
as it is. */
if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
{
svn_string_t *renumbered_mergeinfo;
/* ### Need to cast away const. We cannot change the declaration of
* ### this function since it is part of svn_repos_parse_fns2_t. */
svn_string_t *prop_val = (svn_string_t *)value;
svn_string_t *new_value;
svn_error_t *err;
/* Tolerate mergeinfo with "\r\n" line endings because some
dumpstream sources might contain as much. If so normalize
the line endings to '\n' and make a notification to
PARSE_BATON->FEEDBACK_STREAM that we have made this
correction. */
if (strstr(prop_val->data, "\r"))
err = adjust_mergeinfo_property(rb, &new_value, value, nb->pool);
if (err)
{
const char *prop_eol_normalized;
SVN_ERR(svn_subst_translate_cstring2(prop_val->data,
&prop_eol_normalized,
"\n", /* translate to LF */
FALSE, /* no repair */
NULL, /* no keywords */
FALSE, /* no expansion */
nb->pool));
prop_val->data = prop_eol_normalized;
prop_val->len = strlen(prop_eol_normalized);
if (pb->validate_props)
{
return svn_error_quick_wrap(
err,
_("Invalid svn:mergeinfo value"));
}
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_normalized_mergeinfo;
pb->notify_func(pb->notify_baton, pb->notify, nb->pool);
}
}
svn_repos_notify_t *notify
= svn_repos_notify_create(svn_repos_notify_warning,
pb->notify_pool);
/* Renumber mergeinfo as appropriate. */
SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, prop_val, rb,
nb->pool));
value = renumbered_mergeinfo;
if (pb->parent_dir)
notify->warning = svn_repos__notify_warning_invalid_mergeinfo;
notify->warning_str = _("Invalid svn:mergeinfo value; "
"leaving unchanged");
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
svn_error_clear(err);
}
else
{
/* Prefix the merge source paths with PB->parent_dir. */
/* ASSUMPTION: All source paths are included in the dump stream. */
svn_string_t *mergeinfo_val;
SVN_ERR(prefix_mergeinfo_paths(&mergeinfo_val, value,
pb->parent_dir, nb->pool));
value = mergeinfo_val;
value = new_value;
}
}
@ -896,8 +959,13 @@ close_node(void *baton)
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_node_done;
pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
/* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_load_node_done,
pb->notify_pool);
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
return SVN_NO_ERROR;
@ -1016,12 +1084,17 @@ close_revision(void *baton)
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_txn_committed;
pb->notify->new_revision = committed_rev;
pb->notify->old_revision = ((committed_rev == rb->rev)
/* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_load_txn_committed,
pb->notify_pool);
notify->new_revision = committed_rev;
notify->old_revision = ((committed_rev == rb->rev)
? SVN_INVALID_REVNUM
: rb->rev);
pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
return SVN_NO_ERROR;
@ -1079,10 +1152,10 @@ svn_repos_get_fs_build_parser4(const svn_repos_parse_fns3_t **callbacks,
pb->validate_props = validate_props;
pb->notify_func = notify_func;
pb->notify_baton = notify_baton;
pb->notify = svn_repos_notify_create(svn_repos_notify_load_txn_start, pool);
pb->uuid_action = uuid_action;
pb->parent_dir = parent_dir;
pb->pool = pool;
pb->notify_pool = svn_pool_create(pool);
pb->rev_map = apr_hash_make(pool);
pb->oldest_old_rev = SVN_INVALID_REVNUM;
pb->last_rev_mapped = SVN_INVALID_REVNUM;

View File

@ -726,23 +726,6 @@ svn_repos_trace_node_locations(svn_fs_t *fs,
if (! prev_path)
break;
if (authz_read_func)
{
svn_boolean_t readable;
svn_fs_root_t *tmp_root;
SVN_ERR(svn_fs_revision_root(&tmp_root, fs, revision, currpool));
SVN_ERR(authz_read_func(&readable, tmp_root, path,
authz_read_baton, currpool));
if (! readable)
{
svn_pool_destroy(lastpool);
svn_pool_destroy(currpool);
return SVN_NO_ERROR;
}
}
/* Assign the current path to all younger revisions until we reach
the copy target rev. */
while ((revision_ptr < revision_ptr_end)
@ -765,6 +748,20 @@ svn_repos_trace_node_locations(svn_fs_t *fs,
path = prev_path;
revision = prev_rev;
if (authz_read_func)
{
svn_boolean_t readable;
SVN_ERR(svn_fs_revision_root(&root, fs, revision, currpool));
SVN_ERR(authz_read_func(&readable, root, path,
authz_read_baton, currpool));
if (!readable)
{
svn_pool_destroy(lastpool);
svn_pool_destroy(currpool);
return SVN_NO_ERROR;
}
}
/* Clear last pool and switch. */
svn_pool_clear(lastpool);
tmppool = lastpool;

View File

@ -101,6 +101,21 @@
* on their hash key.
*/
/* APR's read-write lock implementation on Windows is horribly inefficient.
* Even with very low contention a runtime overhead of 35% percent has been
* measured for 'svn-bench null-export' over ra_serf.
*
* Use a simple mutex on Windows. Because there is one mutex per segment,
* large machines should (and usually can) be configured with large caches
* such that read contention is kept low. This is basically the situation
* we head before 1.8.
*/
#ifdef WIN32
# define USE_SIMPLE_MUTEX 1
#else
# define USE_SIMPLE_MUTEX 0
#endif
/* A 16-way associative cache seems to be a good compromise between
* performance (worst-case lookups) and efficiency-loss due to collisions.
*
@ -465,11 +480,15 @@ struct svn_membuffer_t
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
# if USE_SIMPLE_MUTEX
svn_mutex__t *lock;
# else
apr_thread_rwlock_t *lock;
# endif
/* If set, write access will wait until they get exclusive access.
* Otherwise, they will become no-ops if the segment is currently
* read-locked.
* read-locked. Only used when LOCK is an r/w lock.
*/
svn_boolean_t allow_blocking_writes;
#endif
@ -489,12 +508,16 @@ static svn_error_t *
read_lock_cache(svn_membuffer_t *cache)
{
#if APR_HAS_THREADS
# if USE_SIMPLE_MUTEX
return svn_mutex__lock(cache->lock);
# else
if (cache->lock)
{
apr_status_t status = apr_thread_rwlock_rdlock(cache->lock);
if (status)
return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
}
# endif
#endif
return SVN_NO_ERROR;
}
@ -505,6 +528,12 @@ static svn_error_t *
write_lock_cache(svn_membuffer_t *cache, svn_boolean_t *success)
{
#if APR_HAS_THREADS
# if USE_SIMPLE_MUTEX
return svn_mutex__lock(cache->lock);
# else
if (cache->lock)
{
apr_status_t status;
@ -526,6 +555,8 @@ write_lock_cache(svn_membuffer_t *cache, svn_boolean_t *success)
return svn_error_wrap_apr(status,
_("Can't write-lock cache mutex"));
}
# endif
#endif
return SVN_NO_ERROR;
}
@ -537,10 +568,18 @@ static svn_error_t *
force_write_lock_cache(svn_membuffer_t *cache)
{
#if APR_HAS_THREADS
# if USE_SIMPLE_MUTEX
return svn_mutex__lock(cache->lock);
# else
apr_status_t status = apr_thread_rwlock_wrlock(cache->lock);
if (status)
return svn_error_wrap_apr(status,
_("Can't write-lock cache mutex"));
# endif
#endif
return SVN_NO_ERROR;
}
@ -552,6 +591,12 @@ static svn_error_t *
unlock_cache(svn_membuffer_t *cache, svn_error_t *err)
{
#if APR_HAS_THREADS
# if USE_SIMPLE_MUTEX
return svn_mutex__unlock(cache->lock, err);
# else
if (cache->lock)
{
apr_status_t status = apr_thread_rwlock_unlock(cache->lock);
@ -561,6 +606,8 @@ unlock_cache(svn_membuffer_t *cache, svn_error_t *err)
if (status)
return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
}
# endif
#endif
return err;
}
@ -1290,6 +1337,12 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache,
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
# if USE_SIMPLE_MUTEX
SVN_ERR(svn_mutex__init(&c[seg].lock, thread_safe, pool));
# else
c[seg].lock = NULL;
if (thread_safe)
{
@ -1299,6 +1352,8 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache,
return svn_error_wrap_apr(status, _("Can't create cache mutex"));
}
# endif
/* Select the behavior of write operations.
*/
c[seg].allow_blocking_writes = allow_blocking_writes;

View File

@ -487,14 +487,15 @@ make_string_from_option(const char **valuep, svn_config_t *cfg,
expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool);
opt->expanded = TRUE;
if (!x_pool)
if (x_pool != cfg->x_pool)
{
/* Grab the fully expanded value from tmp_pool before its
disappearing act. */
if (opt->x_value)
opt->x_value = apr_pstrmemdup(cfg->x_pool, opt->x_value,
strlen(opt->x_value));
svn_pool_destroy(tmp_pool);
if (!x_pool)
svn_pool_destroy(tmp_pool);
}
}
else

View File

@ -28,6 +28,7 @@
#include "svn_private_config.h"
#include "private/svn_mutex.h"
#include "private/svn_atomic.h"
/* A mutex to protect our global pool and cache. */
static svn_mutex__t *dso_mutex = NULL;
@ -41,18 +42,18 @@ static apr_hash_t *dso_cache;
/* Just an arbitrary location in memory... */
static int not_there_sentinel;
static volatile svn_atomic_t atomic_init_status = 0;
/* A specific value we store in the dso_cache to indicate that the
library wasn't found. This keeps us from allocating extra memory
from dso_pool when trying to find libraries we already know aren't
there. */
#define NOT_THERE ((void *) &not_there_sentinel)
svn_error_t *
svn_dso_initialize2(void)
static svn_error_t *
atomic_init_func(void *baton,
apr_pool_t *pool)
{
if (dso_pool)
return SVN_NO_ERROR;
dso_pool = svn_pool_create(NULL);
SVN_ERR(svn_mutex__init(&dso_mutex, TRUE, dso_pool));
@ -61,6 +62,15 @@ svn_dso_initialize2(void)
return SVN_NO_ERROR;
}
svn_error_t *
svn_dso_initialize2(void)
{
SVN_ERR(svn_atomic__init_once(&atomic_init_status, atomic_init_func,
NULL, NULL));
return SVN_NO_ERROR;
}
#if APR_HAS_DSO
static svn_error_t *
svn_dso_load_internal(apr_dso_handle_t **dso, const char *fname)
@ -107,8 +117,7 @@ svn_dso_load_internal(apr_dso_handle_t **dso, const char *fname)
svn_error_t *
svn_dso_load(apr_dso_handle_t **dso, const char *fname)
{
if (! dso_pool)
SVN_ERR(svn_dso_initialize2());
SVN_ERR(svn_dso_initialize2());
SVN_MUTEX__WITH_LOCK(dso_mutex, svn_dso_load_internal(dso, fname));

View File

@ -289,6 +289,8 @@ svn_error_compose(svn_error_t *chain, svn_error_t *new_err)
*chain = *new_err;
if (chain->message)
chain->message = apr_pstrdup(pool, new_err->message);
if (chain->file)
chain->file = apr_pstrdup(pool, new_err->file);
chain->pool = pool;
#if defined(SVN_DEBUG)
if (! new_err->child)
@ -358,6 +360,8 @@ svn_error_dup(svn_error_t *err)
tmp_err->pool = pool;
if (tmp_err->message)
tmp_err->message = apr_pstrdup(pool, tmp_err->message);
if (tmp_err->file)
tmp_err->file = apr_pstrdup(pool, tmp_err->file);
}
#if defined(SVN_DEBUG)

View File

@ -72,6 +72,9 @@
#include "svn_cmdline.h"
#include "svn_checksum.h"
#include "svn_string.h"
#include "svn_hash.h"
#include "svn_user.h"
#include "svn_dirent_uri.h"
#include "private/svn_auth_private.h"
@ -80,6 +83,7 @@
#ifdef SVN_HAVE_GPG_AGENT
#define BUFFER_SIZE 1024
#define ATTEMPT_PARAMETER "svn.simple.gpg_agent.attempt"
/* Modify STR in-place such that blanks are escaped as required by the
* gpg-agent protocol. Return a pointer to STR. */
@ -98,6 +102,24 @@ escape_blanks(char *str)
return str;
}
/* Generate the string CACHE_ID_P based on the REALMSTRING allocated in
* RESULT_POOL using SCRATCH_POOL for temporary allocations. This is similar
* to other password caching mechanisms. */
static svn_error_t *
get_cache_id(const char **cache_id_p, const char *realmstring,
apr_pool_t *scratch_pool, apr_pool_t *result_pool)
{
const char *cache_id = NULL;
svn_checksum_t *digest = NULL;
SVN_ERR(svn_checksum(&digest, svn_checksum_md5, realmstring,
strlen(realmstring), scratch_pool));
cache_id = svn_checksum_to_cstring(digest, result_pool);
*cache_id_p = cache_id;
return SVN_NO_ERROR;
}
/* Attempt to read a gpg-agent response message from the socket SD into
* buffer BUF. Buf is assumed to be N bytes large. Return TRUE if a response
* message could be read that fits into the buffer. Else return FALSE.
@ -156,6 +178,17 @@ send_option(int sd, char *buf, size_t n, const char *option, const char *value,
return (strncmp(buf, "OK", 2) == 0);
}
/* Send the BYE command and disconnect from the gpg-agent. Doing this avoids
* gpg-agent emitting a "Connection reset by peer" log message with some
* versions of gpg-agent. */
static void
bye_gpg_agent(int sd)
{
/* don't bother to check the result of the write, it either worked or it
* didn't, but either way we're closing. */
write(sd, "BYE\n", 4);
close(sd);
}
/* Locate a running GPG Agent, and return an open file descriptor
* for communication with the agent in *NEW_SD. If no running agent
@ -173,17 +206,34 @@ find_running_gpg_agent(int *new_sd, apr_pool_t *pool)
*new_sd = -1;
/* This implements the method of finding the socket as described in
* the gpg-agent man page under the --use-standard-socket option.
* The manage page misleadingly says the standard socket is
* "named 'S.gpg-agent' located in the home directory." The standard
* socket path is actually in the .gnupg directory in the home directory,
* i.e. ~/.gnupg/S.gpg-agent */
gpg_agent_info = getenv("GPG_AGENT_INFO");
if (gpg_agent_info != NULL)
{
apr_array_header_t *socket_details;
/* For reference GPG_AGENT_INFO consists of 3 : separated fields.
* The path to the socket, the pid of the gpg-agent process and
* finally the version of the protocol the agent talks. */
socket_details = svn_cstring_split(gpg_agent_info, ":", TRUE,
pool);
socket_name = APR_ARRAY_IDX(socket_details, 0, const char *);
}
else
return SVN_NO_ERROR;
{
const char *homedir = svn_user_get_homedir(pool);
if (!homedir)
return SVN_NO_ERROR;
socket_name = svn_dirent_join_many(pool, homedir, ".gnupg",
"S.gpg-agent", NULL);
}
if (socket_name != NULL)
{
@ -210,13 +260,13 @@ find_running_gpg_agent(int *new_sd, apr_pool_t *pool)
buffer = apr_palloc(pool, BUFFER_SIZE);
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
if (strncmp(buffer, "OK", 2) != 0)
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
@ -226,19 +276,19 @@ find_running_gpg_agent(int *new_sd, apr_pool_t *pool)
request = "GETINFO socket_name\n";
if (write(sd, request, strlen(request)) == -1)
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
if (strncmp(buffer, "D", 1) == 0)
p = &buffer[2];
if (!p)
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
ep = strchr(p, '\n');
@ -246,18 +296,18 @@ find_running_gpg_agent(int *new_sd, apr_pool_t *pool)
*ep = '\0';
if (strcmp(socket_name, p) != 0)
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
/* The agent will terminate its response with "OK". */
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
if (strncmp(buffer, "OK", 2) != 0)
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
@ -265,6 +315,55 @@ find_running_gpg_agent(int *new_sd, apr_pool_t *pool)
return SVN_NO_ERROR;
}
static svn_boolean_t
send_options(int sd, char *buf, size_t n, apr_pool_t *scratch_pool)
{
const char *tty_name;
const char *tty_type;
const char *lc_ctype;
const char *display;
/* Send TTY_NAME to the gpg-agent daemon. */
tty_name = getenv("GPG_TTY");
if (tty_name != NULL)
{
if (!send_option(sd, buf, n, "ttyname", tty_name, scratch_pool))
return FALSE;
}
/* Send TTY_TYPE to the gpg-agent daemon. */
tty_type = getenv("TERM");
if (tty_type != NULL)
{
if (!send_option(sd, buf, n, "ttytype", tty_type, scratch_pool))
return FALSE;
}
/* Compute LC_CTYPE. */
lc_ctype = getenv("LC_ALL");
if (lc_ctype == NULL)
lc_ctype = getenv("LC_CTYPE");
if (lc_ctype == NULL)
lc_ctype = getenv("LANG");
/* Send LC_CTYPE to the gpg-agent daemon. */
if (lc_ctype != NULL)
{
if (!send_option(sd, buf, n, "lc-ctype", lc_ctype, scratch_pool))
return FALSE;
}
/* Send DISPLAY to the gpg-agent daemon. */
display = getenv("DISPLAY");
if (display != NULL)
{
if (!send_option(sd, buf, n, "display", display, scratch_pool))
return FALSE;
}
return TRUE;
}
/* Implementation of svn_auth__password_get_t that retrieves the password
from gpg-agent */
static svn_error_t *
@ -283,101 +382,59 @@ password_get_gpg_agent(svn_boolean_t *done,
char *buffer;
const char *request = NULL;
const char *cache_id = NULL;
const char *tty_name;
const char *tty_type;
const char *lc_ctype;
const char *display;
svn_checksum_t *digest = NULL;
char *password_prompt;
char *realm_prompt;
char *error_prompt;
int *attempt;
*done = FALSE;
attempt = svn_hash_gets(parameters, ATTEMPT_PARAMETER);
SVN_ERR(find_running_gpg_agent(&sd, pool));
if (sd == -1)
return SVN_NO_ERROR;
buffer = apr_palloc(pool, BUFFER_SIZE);
/* Send TTY_NAME to the gpg-agent daemon. */
tty_name = getenv("GPG_TTY");
if (tty_name != NULL)
if (!send_options(sd, buffer, BUFFER_SIZE, pool))
{
if (!send_option(sd, buffer, BUFFER_SIZE, "ttyname", tty_name, pool))
{
close(sd);
return SVN_NO_ERROR;
}
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
/* Send TTY_TYPE to the gpg-agent daemon. */
tty_type = getenv("TERM");
if (tty_type != NULL)
{
if (!send_option(sd, buffer, BUFFER_SIZE, "ttytype", tty_type, pool))
{
close(sd);
return SVN_NO_ERROR;
}
}
/* Compute LC_CTYPE. */
lc_ctype = getenv("LC_ALL");
if (lc_ctype == NULL)
lc_ctype = getenv("LC_CTYPE");
if (lc_ctype == NULL)
lc_ctype = getenv("LANG");
/* Send LC_CTYPE to the gpg-agent daemon. */
if (lc_ctype != NULL)
{
if (!send_option(sd, buffer, BUFFER_SIZE, "lc-ctype", lc_ctype, pool))
{
close(sd);
return SVN_NO_ERROR;
}
}
/* Send DISPLAY to the gpg-agent daemon. */
display = getenv("DISPLAY");
if (display != NULL)
{
if (!send_option(sd, buffer, BUFFER_SIZE, "display", display, pool))
{
close(sd);
return SVN_NO_ERROR;
}
}
/* Create the CACHE_ID which will be generated based on REALMSTRING similar
to other password caching mechanisms. */
SVN_ERR(svn_checksum(&digest, svn_checksum_md5, realmstring,
strlen(realmstring), pool));
cache_id = svn_checksum_to_cstring(digest, pool);
SVN_ERR(get_cache_id(&cache_id, realmstring, pool, pool));
password_prompt = apr_psprintf(pool, _("Password for '%s': "), username);
realm_prompt = apr_psprintf(pool, _("Enter your Subversion password for %s"),
realmstring);
if (*attempt == 1)
/* X means no error to the gpg-agent protocol */
error_prompt = apr_pstrdup(pool, "X");
else
error_prompt = apr_pstrdup(pool, _("Authentication failed"));
request = apr_psprintf(pool,
"GET_PASSPHRASE --data %s--repeat=1 "
"%s X %s %s\n",
"GET_PASSPHRASE --data %s"
"%s %s %s %s\n",
non_interactive ? "--no-ask " : "",
cache_id,
escape_blanks(error_prompt),
escape_blanks(password_prompt),
escape_blanks(realm_prompt));
if (write(sd, request, strlen(request)) == -1)
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
close(sd);
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
close(sd);
bye_gpg_agent(sd);
if (strncmp(buffer, "ERR", 3) == 0)
return SVN_NO_ERROR;
@ -424,7 +481,7 @@ password_set_gpg_agent(svn_boolean_t *done,
if (sd == -1)
return SVN_NO_ERROR;
close(sd);
bye_gpg_agent(sd);
*done = TRUE;
return SVN_NO_ERROR;
@ -440,11 +497,108 @@ simple_gpg_agent_first_creds(void **credentials,
const char *realmstring,
apr_pool_t *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);
svn_error_t *err;
int *attempt = apr_palloc(pool, sizeof(*attempt));
*attempt = 1;
svn_hash_sets(parameters, ATTEMPT_PARAMETER, attempt);
err = svn_auth__simple_creds_cache_get(credentials, iter_baton,
provider_baton, parameters,
realmstring, password_get_gpg_agent,
SVN_AUTH__GPG_AGENT_PASSWORD_TYPE,
pool);
*iter_baton = attempt;
return err;
}
/* An implementation of svn_auth_provider_t::next_credentials() */
static svn_error_t *
simple_gpg_agent_next_creds(void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
int *attempt = (int *)iter_baton;
int sd;
char *buffer;
const char *cache_id = NULL;
const char *request = NULL;
*credentials = NULL;
/* The users previous credentials failed so first remove the cached entry,
* before trying to retrieve them again. Because gpg-agent stores cached
* credentials immediately upon retrieving them, this gives us the
* opportunity to remove the invalid credentials and prompt the
* user again. While it's possible that server side issues could trigger
* this, this cache is ephemeral so at worst we're just speeding up
* when the user would need to re-enter their password. */
if (svn_hash_gets(parameters, SVN_AUTH_PARAM_NON_INTERACTIVE))
{
/* In this case since we're running non-interactively we do not
* want to clear the cache since the user was never prompted by
* gpg-agent to set a password. */
return SVN_NO_ERROR;
}
*attempt = *attempt + 1;
SVN_ERR(find_running_gpg_agent(&sd, pool));
if (sd == -1)
return SVN_NO_ERROR;
buffer = apr_palloc(pool, BUFFER_SIZE);
if (!send_options(sd, buffer, BUFFER_SIZE, pool))
{
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
SVN_ERR(get_cache_id(&cache_id, realmstring, pool, pool));
request = apr_psprintf(pool, "CLEAR_PASSPHRASE %s\n", cache_id);
if (write(sd, request, strlen(request)) == -1)
{
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
if (!receive_from_gpg_agent(sd, buffer, BUFFER_SIZE))
{
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
if (strncmp(buffer, "OK\n", 3) != 0)
{
bye_gpg_agent(sd);
return SVN_NO_ERROR;
}
/* TODO: This attempt limit hard codes it at 3 attempts (or 2 retries)
* which matches svn command line client's retry_limit as set in
* svn_cmdline_create_auth_baton(). It would be nice to have that
* limit reflected here but that violates the boundry between the
* prompt provider and the cache provider. gpg-agent is acting as
* both here due to the peculiarties of their design so we'll have to
* live with this for now. Note that when these failures get exceeded
* it'll eventually fall back on the retry limits of whatever prompt
* provider is in effect, so this effectively doubles the limit. */
if (*attempt < 4)
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);
return SVN_NO_ERROR;
}
@ -468,7 +622,7 @@ simple_gpg_agent_save_creds(svn_boolean_t *saved,
static const svn_auth_provider_t gpg_agent_simple_provider = {
SVN_AUTH_CRED_SIMPLE,
simple_gpg_agent_first_creds,
NULL,
simple_gpg_agent_next_creds,
simple_gpg_agent_save_creds
};

View File

@ -1,4 +1,4 @@
/* This file is automatically generated from internal_statements.sql and .dist_sandbox/subversion-1.8.10/subversion/libsvn_subr/token-map.h.
/* This file is automatically generated from internal_statements.sql and .dist_sandbox/subversion-1.8.14/subversion/libsvn_subr/token-map.h.
* Do not edit this file -- edit the source and rerun gen-make.py */
#define STMT_INTERNAL_SAVEPOINT_SVN 0

View File

@ -4675,8 +4675,25 @@ svn_io_open_unique_file3(apr_file_t **file,
* case, but only if the umask allows it. */
if (!using_system_temp_dir)
{
svn_error_t *err;
SVN_ERR(merge_default_file_perms(tempfile, &perms, scratch_pool));
SVN_ERR(file_perms_set2(tempfile, perms, scratch_pool));
err = file_perms_set2(tempfile, perms, scratch_pool);
if (err)
{
if (APR_STATUS_IS_INCOMPLETE(err->apr_err) ||
APR_STATUS_IS_ENOTIMPL(err->apr_err))
svn_error_clear(err);
else
{
const char *message;
message = apr_psprintf(scratch_pool,
_("Can't set permissions on '%s'"),
svn_dirent_local_style(tempname,
scratch_pool));
return svn_error_quick_wrap(err, message);
}
}
}
#endif

View File

@ -611,6 +611,43 @@ svn_rangelist__parse(svn_rangelist_t **rangelist,
return SVN_NO_ERROR;
}
/* Return TRUE, if all ranges in RANGELIST are in ascending order and do
* not overlap and are not adjacent.
*
* ### Can yield false negatives: ranges of differing inheritance are
* allowed to be adjacent.
*
* If this returns FALSE, you probaly want to qsort() the
* ranges and then call svn_rangelist__combine_adjacent_ranges().
*/
static svn_boolean_t
is_rangelist_normalized(svn_rangelist_t *rangelist)
{
int i;
svn_merge_range_t **ranges = (svn_merge_range_t **)rangelist->elts;
for (i = 0; i < rangelist->nelts-1; ++i)
if (ranges[i]->end >= ranges[i+1]->start)
return FALSE;
return TRUE;
}
svn_error_t *
svn_rangelist__canonicalize(svn_rangelist_t *rangelist,
apr_pool_t *scratch_pool)
{
if (! is_rangelist_normalized(rangelist))
{
qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
svn_sort_compare_ranges);
SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
apr_pool_t *scratch_pool)
@ -692,15 +729,11 @@ parse_revision_line(const char **input, const char *end, svn_mergeinfo_t hash,
if (*input != end)
*input = *input + 1;
/* Sort the rangelist, combine adjacent ranges into single ranges,
and make sure there are no overlapping ranges. */
if (rangelist->nelts > 1)
{
qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
svn_sort_compare_ranges);
SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
}
/* Sort the rangelist, combine adjacent ranges into single ranges, and
make sure there are no overlapping ranges. Luckily, most data in
svn:mergeinfo will already be in normalized form and this will be quick.
*/
SVN_ERR(svn_rangelist__canonicalize(rangelist, scratch_pool));
/* Handle any funky mergeinfo with relative merge source paths that
might exist due to issue #3547. It's possible that this issue allowed
@ -1973,6 +2006,22 @@ svn_mergeinfo_sort(svn_mergeinfo_t input, apr_pool_t *pool)
return SVN_NO_ERROR;
}
svn_error_t *
svn_mergeinfo__canonicalize_ranges(svn_mergeinfo_t mergeinfo,
apr_pool_t *scratch_pool)
{
apr_hash_index_t *hi;
for (hi = apr_hash_first(scratch_pool, mergeinfo); hi; hi = apr_hash_next(hi))
{
apr_array_header_t *rl = svn__apr_hash_index_val(hi);
SVN_ERR(svn_rangelist__canonicalize(rl, scratch_pool));
}
return SVN_NO_ERROR;
}
svn_mergeinfo_catalog_t
svn_mergeinfo_catalog_dup(svn_mergeinfo_catalog_t mergeinfo_catalog,
apr_pool_t *pool)

View File

@ -24,7 +24,7 @@
/* Include sqlite3 inline, making all symbols private. */
#ifdef SVN_SQLITE_INLINE
# define SQLITE_OMIT_DEPRECATED
# define SQLITE_OMIT_DEPRECATED 1
# define SQLITE_API static
# if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6 || __APPLE_CC__))
# if !__APPLE_CC__ || __GNUC_MINOR__ >= 6

View File

@ -619,7 +619,7 @@ svn_stringbuf_insert(svn_stringbuf_t *str,
if (bytes + count > str->data && bytes < str->data + str->blocksize)
{
/* special case: BYTES overlaps with this string -> copy the source */
const char *temp = apr_pstrndup(str->pool, bytes, count);
const char *temp = apr_pmemdup(str->pool, bytes, count);
svn_stringbuf_insert(str, pos, temp, count);
}
else
@ -659,7 +659,7 @@ svn_stringbuf_replace(svn_stringbuf_t *str,
if (bytes + new_count > str->data && bytes < str->data + str->blocksize)
{
/* special case: BYTES overlaps with this string -> copy the source */
const char *temp = apr_pstrndup(str->pool, bytes, new_count);
const char *temp = apr_pmemdup(str->pool, bytes, new_count);
svn_stringbuf_replace(str, pos, old_count, temp, new_count);
}
else

View File

@ -136,7 +136,7 @@ svn_version_extended(svn_boolean_t verbose,
info->build_time = NULL;
info->build_host = SVN_BUILD_HOST;
info->copyright = apr_pstrdup
(pool, _("Copyright (C) 2014 The Apache Software Foundation.\n"
(pool, _("Copyright (C) 2015 The Apache Software Foundation.\n"
"This software consists of contributions made by many people;\n"
"see the NOTICE file for more information.\n"
"Subversion is open source software, see "

View File

@ -965,7 +965,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
repos_relpath,
repos_root_url, repos_uuid,
copyfrom_rev,
NULL /* children */, FALSE, depth,
NULL /* children */, depth,
FALSE /* is_move */,
NULL /* conflicts */,
NULL /* work items */,
scratch_pool));

View File

@ -67,69 +67,13 @@ can_be_cleaned(int *wc_format,
return SVN_NO_ERROR;
}
/* Do a modifed check for LOCAL_ABSPATH, and all working children, to force
timestamp repair. */
/* Dummy svn_wc_status_func4_t implementation */
static svn_error_t *
repair_timestamps(svn_wc__db_t *db,
const char *local_abspath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *scratch_pool)
status_dummy_callback(void *baton,
const char *local_abspath,
const svn_wc_status3_t *status,
apr_pool_t *scratch_pool)
{
svn_node_kind_t kind;
svn_wc__db_status_t status;
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
SVN_ERR(svn_wc__db_read_info(&status, &kind,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL,
db, local_abspath, scratch_pool, scratch_pool));
if (status == svn_wc__db_status_server_excluded
|| status == svn_wc__db_status_deleted
|| status == svn_wc__db_status_excluded
|| status == svn_wc__db_status_not_present)
return SVN_NO_ERROR;
if (kind == svn_node_file
|| kind == svn_node_symlink)
{
svn_boolean_t modified;
SVN_ERR(svn_wc__internal_file_modified_p(&modified,
db, local_abspath, FALSE,
scratch_pool));
}
else if (kind == svn_node_dir)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
const apr_array_header_t *children;
int i;
SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
local_abspath,
scratch_pool,
iterpool));
for (i = 0; i < children->nelts; ++i)
{
const char *child_abspath;
svn_pool_clear(iterpool);
child_abspath = svn_dirent_join(local_abspath,
APR_ARRAY_IDX(children, i,
const char *),
iterpool);
SVN_ERR(repair_timestamps(db, child_abspath,
cancel_func, cancel_baton, iterpool));
}
svn_pool_destroy(iterpool);
}
return SVN_NO_ERROR;
}
@ -184,8 +128,17 @@ cleanup_internal(svn_wc__db_t *db,
SVN_ERR(svn_wc__db_pristine_cleanup(db, dir_abspath, scratch_pool));
}
SVN_ERR(repair_timestamps(db, dir_abspath, cancel_func, cancel_baton,
scratch_pool));
/* Instead of implementing a separate repair step here, use the standard
status walker's optimized implementation, which performs repairs when
there is a lock. */
SVN_ERR(svn_wc__internal_walk_status(db, dir_abspath, svn_depth_infinity,
FALSE /* get_all */,
FALSE /* no_ignore */,
FALSE /* ignore_text_mods */,
NULL /* ignore patterns */,
status_dummy_callback, NULL,
cancel_func, cancel_baton,
scratch_pool));
/* All done, toss the lock */
SVN_ERR(svn_wc__db_wclock_release(db, dir_abspath, scratch_pool));

View File

@ -1642,7 +1642,13 @@ eval_text_conflict_func_result(svn_skel_t **work_items,
}
}
SVN_ERR_ASSERT(install_from_abspath != NULL);
if (install_from_abspath == NULL)
return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("Conflict on '%s' could not be resolved "
"because the chosen version of the file "
"is not available."),
svn_dirent_local_style(local_abspath,
scratch_pool));
{
svn_skel_t *work_item;
@ -1761,6 +1767,7 @@ resolve_text_conflict(svn_skel_t **work_items,
svn_skel_t *work_item;
svn_wc_conflict_description2_t *cdesc;
apr_hash_t *props;
const char *mime_type;
*work_items = NULL;
*was_resolved = FALSE;
@ -1773,8 +1780,9 @@ resolve_text_conflict(svn_skel_t **work_items,
cdesc = svn_wc_conflict_description_create_text2(local_abspath,
scratch_pool);
cdesc->is_binary = FALSE;
cdesc->mime_type = svn_prop_get_value(props, SVN_PROP_MIME_TYPE);
mime_type = svn_prop_get_value(props, SVN_PROP_MIME_TYPE);
cdesc->is_binary = mime_type ? svn_mime_type_is_binary(mime_type) : FALSE;
cdesc->mime_type = mime_type;
cdesc->base_abspath = left_abspath;
cdesc->their_abspath = right_abspath;
cdesc->my_abspath = detranslated_target;
@ -2262,6 +2270,8 @@ svn_wc__read_conflicts(const apr_array_header_t **conflicts,
if (text_conflicted)
{
apr_hash_t *props;
const char *mime_type;
svn_wc_conflict_description2_t *desc;
desc = svn_wc_conflict_description_create_text2(local_abspath,
result_pool);
@ -2270,6 +2280,12 @@ svn_wc__read_conflicts(const apr_array_header_t **conflicts,
desc->src_left_version = left_version;
desc->src_right_version = right_version;
SVN_ERR(svn_wc__db_read_props(&props, db, local_abspath,
scratch_pool, scratch_pool));
mime_type = svn_prop_get_value(props, SVN_PROP_MIME_TYPE);
desc->is_binary = mime_type ? svn_mime_type_is_binary(mime_type) : FALSE;
desc->mime_type = mime_type;
SVN_ERR(svn_wc__conflict_read_text_conflict(&desc->my_abspath,
&desc->base_abspath,
&desc->their_abspath,
@ -2913,6 +2929,13 @@ conflict_status_walker(void *baton,
cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
if ((cd->kind == svn_wc_conflict_kind_property && !cswb->resolve_prop)
|| (cd->kind == svn_wc_conflict_kind_text && !cswb->resolve_text)
|| (cd->kind == svn_wc_conflict_kind_tree && !cswb->resolve_tree))
{
continue; /* Easy out. Don't call resolver func and ignore result */
}
svn_pool_clear(iterpool);
if (my_choice == svn_wc_conflict_choose_unspecified)

View File

@ -891,18 +891,18 @@ remove_node_conflict_markers(svn_wc__db_t *db,
{
const char *marker_abspath;
const char *child_relpath;
const char *child_abpath;
const char *child_abspath;
marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
child_relpath = svn_dirent_is_child(src_dir, marker_abspath, NULL);
child_relpath = svn_dirent_skip_ancestor(src_dir, marker_abspath);
if (child_relpath)
{
child_abpath = svn_dirent_join(dst_dir, child_relpath,
scratch_pool);
child_abspath = svn_dirent_join(dst_dir, child_relpath,
scratch_pool);
SVN_ERR(svn_io_remove_file2(child_abpath, TRUE, scratch_pool));
SVN_ERR(svn_io_remove_file2(child_abspath, TRUE, scratch_pool));
}
}
}
@ -922,7 +922,7 @@ remove_node_conflict_markers(svn_wc__db_t *db,
static svn_error_t *
remove_all_conflict_markers(svn_wc__db_t *db,
const char *src_dir_abspath,
const char *wc_dir_abspath,
const char *dst_dir_abspath,
apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@ -951,7 +951,7 @@ remove_all_conflict_markers(svn_wc__db_t *db,
SVN_ERR(remove_node_conflict_markers(
db,
svn_dirent_join(src_dir_abspath, name, iterpool),
svn_dirent_join(wc_dir_abspath, name, iterpool),
svn_dirent_join(dst_dir_abspath, name, iterpool),
iterpool));
}
if (info->kind == svn_node_dir)
@ -960,7 +960,7 @@ remove_all_conflict_markers(svn_wc__db_t *db,
SVN_ERR(remove_all_conflict_markers(
db,
svn_dirent_join(src_dir_abspath, name, iterpool),
svn_dirent_join(wc_dir_abspath, name, iterpool),
svn_dirent_join(dst_dir_abspath, name, iterpool),
iterpool));
}
}
@ -1033,8 +1033,16 @@ svn_wc__move2(svn_wc_context_t *wc_ctx,
scratch_pool));
if (conflicted)
SVN_ERR(remove_node_conflict_markers(db, src_abspath, dst_abspath,
scratch_pool));
{
/* When we moved a directory, we moved the conflict markers
with the target... if we moved a file we only moved the
file itself and the markers are still in the old location */
SVN_ERR(remove_node_conflict_markers(db, src_abspath,
(kind == svn_node_dir)
? dst_abspath
: src_abspath,
scratch_pool));
}
SVN_ERR(svn_wc__db_op_delete(db, src_abspath,
move_degraded_to_copy ? NULL : dst_abspath,

View File

@ -47,9 +47,6 @@ extern "C" {
svn_wc__db_status_added. When DIFF_PRISTINE is TRUE, report the pristine
version of LOCAL_ABSPATH as ADDED. In this case an
svn_wc__db_status_deleted may shadow an added or deleted node.
If CHANGELIST_HASH is not NULL and LOCAL_ABSPATH's changelist is not
in the changelist, don't report the node.
*/
svn_error_t *
svn_wc__diff_local_only_file(svn_wc__db_t *db,
@ -57,7 +54,6 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,
const char *relpath,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
apr_hash_t *changelist_hash,
svn_boolean_t diff_pristine,
svn_cancel_func_t cancel_func,
void *cancel_baton,
@ -73,9 +69,6 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,
svn_wc__db_status_added. When DIFF_PRISTINE is TRUE, report the pristine
version of LOCAL_ABSPATH as ADDED. In this case an
svn_wc__db_status_deleted may shadow an added or deleted node.
If CHANGELIST_HASH is not NULL and LOCAL_ABSPATH's changelist is not
in the changelist, don't report the node.
*/
svn_error_t *
svn_wc__diff_local_only_dir(svn_wc__db_t *db,
@ -84,7 +77,6 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
svn_depth_t depth,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
apr_hash_t *changelist_hash,
svn_boolean_t diff_pristine,
svn_cancel_func_t cancel_func,
void *cancel_baton,
@ -132,7 +124,6 @@ svn_wc__diff_base_working_diff(svn_wc__db_t *db,
const char *local_abspath,
const char *relpath,
svn_revnum_t revision,
apr_hash_t *changelist_hash,
const svn_diff_tree_processor_t *processor,
void *processor_dir_baton,
svn_boolean_t diff_pristine,
@ -140,6 +131,32 @@ svn_wc__diff_base_working_diff(svn_wc__db_t *db,
void *cancel_baton,
apr_pool_t *scratch_pool);
/* Return a tree processor filter that filters by changelist membership.
*
* This filter only passes on the changes for a file if the file's path
* (in the WC) is assigned to one of the changelists in @a changelist_hash.
* It also passes on the opening and closing of each directory that contains
* such a change, and possibly also of other directories, but not addition
* or deletion or changes to a directory.
*
* If @a changelist_hash is null then no filtering is performed and the
* returned diff processor is driven exactly like the input @a processor.
*
* @a wc_ctx is the WC context and @a root_local_abspath is the WC path of
* the root of the diff (for which relpath = "" in the diff processor).
*
* Allocate the returned diff processor in @a result_pool, or if no
* filtering is required then the input pointer @a processor itself may be
* returned.
*/
const svn_diff_tree_processor_t *
svn_wc__changelist_filter_tree_processor_create(
const svn_diff_tree_processor_t *processor,
svn_wc_context_t *wc_ctx,
const char *root_local_abspath,
apr_hash_t *changelist_hash,
apr_pool_t *result_pool);
#ifdef __cplusplus
}

View File

@ -114,9 +114,6 @@ struct edit_baton_t
/* Possibly diff repos against text-bases instead of working files. */
svn_boolean_t diff_pristine;
/* Hash whose keys are const char * changelist names. */
apr_hash_t *changelist_hash;
/* Cancel function/baton */
svn_cancel_func_t cancel_func;
void *cancel_baton;
@ -238,43 +235,26 @@ struct file_baton_t
* calculating diffs. USE_TEXT_BASE defines whether to compare
* against working files or text-bases. REVERSE_ORDER defines which
* direction to perform the diff.
*
* CHANGELIST_FILTER is a list of const char * changelist names, used to
* filter diff output responses to only those items in one of the
* specified changelists, empty (or NULL altogether) if no changelist
* filtering is requested.
*/
static svn_error_t *
make_edit_baton(struct edit_baton_t **edit_baton,
svn_wc__db_t *db,
const char *anchor_abspath,
const char *target,
const svn_wc_diff_callbacks4_t *callbacks,
void *callback_baton,
const svn_diff_tree_processor_t *processor,
svn_depth_t depth,
svn_boolean_t ignore_ancestry,
svn_boolean_t show_copies_as_adds,
svn_boolean_t use_text_base,
svn_boolean_t reverse_order,
const apr_array_header_t *changelist_filter,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
{
apr_hash_t *changelist_hash = NULL;
struct edit_baton_t *eb;
const svn_diff_tree_processor_t *processor;
SVN_ERR_ASSERT(svn_dirent_is_absolute(anchor_abspath));
if (changelist_filter && changelist_filter->nelts)
SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
pool));
SVN_ERR(svn_wc__wrap_diff_callbacks(&processor,
callbacks, callback_baton, TRUE,
pool, pool));
if (reverse_order)
processor = svn_diff__tree_processor_reverse_create(processor, NULL, pool);
@ -295,7 +275,6 @@ make_edit_baton(struct edit_baton_t **edit_baton,
eb->ignore_ancestry = ignore_ancestry;
eb->local_before_remote = reverse_order;
eb->diff_pristine = use_text_base;
eb->changelist_hash = changelist_hash;
eb->cancel_func = cancel_func;
eb->cancel_baton = cancel_baton;
eb->pool = pool;
@ -409,7 +388,6 @@ svn_wc__diff_base_working_diff(svn_wc__db_t *db,
const char *local_abspath,
const char *relpath,
svn_revnum_t revision,
apr_hash_t *changelist_hash,
const svn_diff_tree_processor_t *processor,
void *processor_dir_baton,
svn_boolean_t diff_pristine,
@ -436,12 +414,11 @@ svn_wc__diff_base_working_diff(svn_wc__db_t *db,
apr_hash_t *base_props;
apr_hash_t *local_props;
apr_array_header_t *prop_changes;
const char *changelist;
SVN_ERR(svn_wc__db_read_info(&status, NULL, &db_revision, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, &working_checksum, NULL,
NULL, NULL, NULL, NULL, NULL, &recorded_size,
&recorded_time, &changelist, NULL, NULL,
&recorded_time, NULL, NULL, NULL,
&had_props, &props_mod, NULL, NULL, NULL,
db, local_abspath, scratch_pool, scratch_pool));
checksum = working_checksum;
@ -450,12 +427,6 @@ svn_wc__diff_base_working_diff(svn_wc__db_t *db,
|| status == svn_wc__db_status_added
|| (status == svn_wc__db_status_deleted && diff_pristine));
/* If the item is not a member of a specified changelist (and there are
some specified changelists), skip it. */
if (changelist_hash && !svn_hash_gets(changelist_hash, changelist))
return SVN_NO_ERROR;
if (status != svn_wc__db_status_normal)
{
SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db_revision,
@ -780,7 +751,6 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
child_relpath,
eb->processor, dir_baton,
eb->changelist_hash,
eb->diff_pristine,
eb->cancel_func,
eb->cancel_baton,
@ -790,7 +760,6 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
child_relpath,
depth_below_here,
eb->processor, dir_baton,
eb->changelist_hash,
eb->diff_pristine,
eb->cancel_func,
eb->cancel_baton,
@ -826,7 +795,6 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
db, child_abspath,
child_relpath,
eb->revnum,
eb->changelist_hash,
eb->processor, dir_baton,
eb->diff_pristine,
eb->cancel_func,
@ -849,7 +817,6 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
child_relpath,
eb->processor, dir_baton,
eb->changelist_hash,
eb->diff_pristine,
eb->cancel_func,
eb->cancel_baton,
@ -858,7 +825,6 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
child_relpath, depth_below_here,
eb->processor, dir_baton,
eb->changelist_hash,
eb->diff_pristine,
eb->cancel_func,
eb->cancel_baton,
@ -870,13 +836,9 @@ walk_local_nodes_diff(struct edit_baton_t *eb,
if (compared)
return SVN_NO_ERROR;
/* Check for local property mods on this directory, if we haven't
already reported them and we aren't changelist-filted.
### it should be noted that we do not currently allow directories
### to be part of changelists, so if a changelist is provided, the
### changelist check will always fail. */
/* Check for local property mods on this directory, if we haven't
already reported them. */
if (! skip
&& ! eb->changelist_hash
&& ! in_anchor_not_target
&& props_mod)
{
@ -919,7 +881,6 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,
const char *relpath,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
apr_hash_t *changelist_hash,
svn_boolean_t diff_pristine,
svn_cancel_func_t cancel_func,
void *cancel_baton,
@ -932,7 +893,6 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,
const svn_checksum_t *checksum;
const char *original_repos_relpath;
svn_revnum_t original_revision;
const char *changelist;
svn_boolean_t had_props;
svn_boolean_t props_mod;
apr_hash_t *pristine_props;
@ -948,7 +908,7 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,
NULL, NULL, NULL, NULL, &checksum, NULL,
&original_repos_relpath, NULL, NULL,
&original_revision, NULL, NULL, NULL,
&changelist, NULL, NULL, &had_props,
NULL, NULL, NULL, &had_props,
&props_mod, NULL, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool));
@ -959,10 +919,6 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,
|| (status == svn_wc__db_status_deleted && diff_pristine)));
if (changelist && changelist_hash
&& !svn_hash_gets(changelist_hash, changelist))
return SVN_NO_ERROR;
if (status == svn_wc__db_status_deleted)
{
assert(diff_pristine);
@ -1065,12 +1021,19 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
svn_depth_t depth,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
apr_hash_t *changelist_hash,
svn_boolean_t diff_pristine,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_status_t status;
svn_node_kind_t kind;
svn_boolean_t had_props;
svn_boolean_t props_mod;
const char *original_repos_relpath;
svn_revnum_t original_revision;
svn_diff_source_t *copyfrom_src = NULL;
apr_hash_t *pristine_props;
const apr_array_header_t *children;
int i;
apr_pool_t *iterpool;
@ -1083,6 +1046,47 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
apr_hash_t *nodes;
apr_hash_t *conflicts;
SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
&original_repos_relpath, NULL, NULL,
&original_revision, NULL, NULL, NULL,
NULL, NULL, NULL, &had_props,
&props_mod, NULL, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool));
if (original_repos_relpath)
{
copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
copyfrom_src->repos_relpath = original_repos_relpath;
}
/* svn_wc__db_status_incomplete should never happen, as the result won't be
stable or guaranteed related to what is in the repository for this
revision, but without this it would be hard to diagnose that status... */
assert(kind == svn_node_dir
&& (status == svn_wc__db_status_normal
|| status == svn_wc__db_status_incomplete
|| status == svn_wc__db_status_added
|| (status == svn_wc__db_status_deleted && diff_pristine)));
if (status == svn_wc__db_status_deleted)
{
assert(diff_pristine);
SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, &had_props,
&pristine_props,
db, local_abspath,
scratch_pool, scratch_pool));
props_mod = FALSE;
}
else if (!had_props)
pristine_props = apr_hash_make(scratch_pool);
else
SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props,
db, local_abspath,
scratch_pool, scratch_pool));
/* Report the addition of the directory's contents. */
iterpool = svn_pool_create(scratch_pool);
@ -1090,10 +1094,11 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
relpath,
NULL,
right_src,
NULL /* copyfrom_src */,
copyfrom_src,
processor_parent_baton,
processor,
scratch_pool, iterpool));
/* ### skip_children is not used */
SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts, db, local_abspath,
scratch_pool, iterpool));
@ -1138,7 +1143,6 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
child_relpath,
processor, pdb,
changelist_hash,
diff_pristine,
cancel_func, cancel_baton,
scratch_pool));
@ -1150,7 +1154,6 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
child_relpath, depth_below_here,
processor, pdb,
changelist_hash,
diff_pristine,
cancel_func, cancel_baton,
iterpool));
@ -1165,17 +1168,19 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,
if (!skip)
{
apr_hash_t *right_props;
if (diff_pristine)
SVN_ERR(svn_wc__db_read_pristine_props(&right_props, db, local_abspath,
scratch_pool, scratch_pool));
if (props_mod && !diff_pristine)
SVN_ERR(svn_wc__db_read_props(&right_props, db, local_abspath,
scratch_pool, scratch_pool));
else
SVN_ERR(svn_wc__get_actual_props(&right_props, db, local_abspath,
scratch_pool, scratch_pool));
right_props = svn_prop_hash_dup(pristine_props, scratch_pool);
SVN_ERR(processor->dir_added(relpath,
NULL /* copyfrom_src */,
copyfrom_src,
right_src,
NULL,
copyfrom_src
? pristine_props
: NULL,
right_props,
pdb,
processor,
@ -1246,7 +1251,6 @@ handle_local_only(struct dir_baton_t *pb,
svn_relpath_join(pb->relpath, name, scratch_pool),
repos_delete ? svn_depth_infinity : depth,
eb->processor, pb->pdb,
eb->changelist_hash,
eb->diff_pristine,
eb->cancel_func, eb->cancel_baton,
scratch_pool));
@ -1257,7 +1261,6 @@ handle_local_only(struct dir_baton_t *pb,
svn_dirent_join(pb->local_abspath, name, scratch_pool),
svn_relpath_join(pb->relpath, name, scratch_pool),
eb->processor, pb->pdb,
eb->changelist_hash,
eb->diff_pristine,
eb->cancel_func, eb->cancel_baton,
scratch_pool));
@ -2032,7 +2035,14 @@ close_file(void *file_baton,
const char *repos_file;
apr_hash_t *repos_props;
if (!fb->skip && expected_md5_digest != NULL)
if (fb->skip)
{
svn_pool_destroy(fb->pool); /* destroys scratch_pool and fb */
SVN_ERR(maybe_done(pb));
return SVN_NO_ERROR;
}
if (expected_md5_digest != NULL)
{
svn_checksum_t *expected_checksum;
const svn_checksum_t *result_checksum;
@ -2087,11 +2097,7 @@ close_file(void *file_baton,
}
}
if (fb->skip)
{
/* Diff processor requested skipping information */
}
else if (fb->repos_only)
if (fb->repos_only)
{
SVN_ERR(eb->processor->file_deleted(fb->relpath,
fb->left_src,
@ -2271,6 +2277,7 @@ svn_wc__get_diff_editor(const svn_delta_editor_t **editor,
struct svn_wc__shim_fetch_baton_t *sfb;
svn_delta_shim_callbacks_t *shim_callbacks =
svn_delta_shim_callbacks_default(result_pool);
const svn_diff_tree_processor_t *diff_processor;
SVN_ERR_ASSERT(svn_dirent_is_absolute(anchor_abspath));
@ -2278,12 +2285,28 @@ svn_wc__get_diff_editor(const svn_delta_editor_t **editor,
if (use_git_diff_format)
show_copies_as_adds = TRUE;
SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
callbacks, callback_baton, TRUE,
result_pool, scratch_pool));
/* Apply changelist filtering to the output */
if (changelist_filter && changelist_filter->nelts)
{
apr_hash_t *changelist_hash;
SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
result_pool));
diff_processor = svn_wc__changelist_filter_tree_processor_create(
diff_processor, wc_ctx, anchor_abspath,
changelist_hash, result_pool);
}
SVN_ERR(make_edit_baton(&eb,
wc_ctx->db,
anchor_abspath, target,
callbacks, callback_baton,
diff_processor,
depth, ignore_ancestry, show_copies_as_adds,
use_text_base, reverse_order, changelist_filter,
use_text_base, reverse_order,
cancel_func, cancel_baton,
result_pool));
@ -2390,8 +2413,8 @@ wrap_dir_opened(void **new_dir_baton,
wc_diff_wrap_baton_t *wb = processor->baton;
svn_boolean_t tree_conflicted = FALSE;
assert(left_source || right_source);
assert(!copyfrom_source || !right_source);
assert(left_source || right_source); /* Must exist at one point. */
assert(!left_source || !copyfrom_source); /* Either existed or added. */
/* Maybe store state and tree_conflicted in baton? */
if (left_source != NULL)
@ -2749,3 +2772,329 @@ svn_wc__wrap_diff_callbacks(const svn_diff_tree_processor_t **diff_processor,
*diff_processor = processor;
return SVN_NO_ERROR;
}
/* =====================================================================
* A tree processor filter that filters by changelist membership
* =====================================================================
*
* The current implementation queries the WC for the changelist of each
* file as it comes through, and sets the 'skip' flag for a non-matching
* file.
*
* (It doesn't set the 'skip' flag for a directory, as we need to receive
* the changed/added/deleted/closed call to know when it is closed, in
* order to preserve the strict open-close semantics for the wrapped tree
* processor.)
*
* It passes on the opening and closing of every directory, even if there
* are no file changes to be passed on inside that directory.
*/
typedef struct filter_tree_baton_t
{
const svn_diff_tree_processor_t *processor;
svn_wc_context_t *wc_ctx;
/* WC path of the root of the diff (where relpath = "") */
const char *root_local_abspath;
/* Hash whose keys are const char * changelist names. */
apr_hash_t *changelist_hash;
} filter_tree_baton_t;
static svn_error_t *
filter_dir_opened(void **new_dir_baton,
svn_boolean_t *skip,
svn_boolean_t *skip_children,
const char *relpath,
const svn_diff_source_t *left_source,
const svn_diff_source_t *right_source,
const svn_diff_source_t *copyfrom_source,
void *parent_dir_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->dir_opened(new_dir_baton, skip, skip_children,
relpath,
left_source, right_source,
copyfrom_source,
parent_dir_baton,
fb->processor,
result_pool, scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_dir_added(const char *relpath,
const svn_diff_source_t *copyfrom_source,
const svn_diff_source_t *right_source,
/*const*/ apr_hash_t *copyfrom_props,
/*const*/ apr_hash_t *right_props,
void *dir_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->dir_closed(relpath,
NULL,
right_source,
dir_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_dir_deleted(const char *relpath,
const svn_diff_source_t *left_source,
/*const*/ apr_hash_t *left_props,
void *dir_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->dir_closed(relpath,
left_source,
NULL,
dir_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_dir_changed(const char *relpath,
const svn_diff_source_t *left_source,
const svn_diff_source_t *right_source,
/*const*/ apr_hash_t *left_props,
/*const*/ apr_hash_t *right_props,
const apr_array_header_t *prop_changes,
void *dir_baton,
const struct svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->dir_closed(relpath,
left_source,
right_source,
dir_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_dir_closed(const char *relpath,
const svn_diff_source_t *left_source,
const svn_diff_source_t *right_source,
void *dir_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->dir_closed(relpath,
left_source,
right_source,
dir_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_file_opened(void **new_file_baton,
svn_boolean_t *skip,
const char *relpath,
const svn_diff_source_t *left_source,
const svn_diff_source_t *right_source,
const svn_diff_source_t *copyfrom_source,
void *dir_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
const char *local_abspath
= svn_dirent_join(fb->root_local_abspath, relpath, scratch_pool);
/* Skip if not a member of a given changelist */
if (! svn_wc__changelist_match(fb->wc_ctx, local_abspath,
fb->changelist_hash, scratch_pool))
{
*skip = TRUE;
return SVN_NO_ERROR;
}
SVN_ERR(fb->processor->file_opened(new_file_baton,
skip,
relpath,
left_source,
right_source,
copyfrom_source,
dir_baton,
fb->processor,
result_pool,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_file_added(const char *relpath,
const svn_diff_source_t *copyfrom_source,
const svn_diff_source_t *right_source,
const char *copyfrom_file,
const char *right_file,
/*const*/ apr_hash_t *copyfrom_props,
/*const*/ apr_hash_t *right_props,
void *file_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->file_added(relpath,
copyfrom_source,
right_source,
copyfrom_file,
right_file,
copyfrom_props,
right_props,
file_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_file_deleted(const char *relpath,
const svn_diff_source_t *left_source,
const char *left_file,
/*const*/ apr_hash_t *left_props,
void *file_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->file_deleted(relpath,
left_source,
left_file,
left_props,
file_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_file_changed(const char *relpath,
const svn_diff_source_t *left_source,
const svn_diff_source_t *right_source,
const char *left_file,
const char *right_file,
/*const*/ apr_hash_t *left_props,
/*const*/ apr_hash_t *right_props,
svn_boolean_t file_modified,
const apr_array_header_t *prop_changes,
void *file_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->file_changed(relpath,
left_source,
right_source,
left_file,
right_file,
left_props,
right_props,
file_modified,
prop_changes,
file_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_file_closed(const char *relpath,
const svn_diff_source_t *left_source,
const svn_diff_source_t *right_source,
void *file_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->file_closed(relpath,
left_source,
right_source,
file_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
filter_node_absent(const char *relpath,
void *dir_baton,
const svn_diff_tree_processor_t *processor,
apr_pool_t *scratch_pool)
{
struct filter_tree_baton_t *fb = processor->baton;
SVN_ERR(fb->processor->node_absent(relpath,
dir_baton,
fb->processor,
scratch_pool));
return SVN_NO_ERROR;
}
const svn_diff_tree_processor_t *
svn_wc__changelist_filter_tree_processor_create(
const svn_diff_tree_processor_t *processor,
svn_wc_context_t *wc_ctx,
const char *root_local_abspath,
apr_hash_t *changelist_hash,
apr_pool_t *result_pool)
{
struct filter_tree_baton_t *fb;
svn_diff_tree_processor_t *filter;
if (! changelist_hash)
return processor;
fb = apr_pcalloc(result_pool, sizeof(*fb));
fb->processor = processor;
fb->wc_ctx = wc_ctx;
fb->root_local_abspath = root_local_abspath;
fb->changelist_hash = changelist_hash;
filter = svn_diff__tree_processor_create(fb, result_pool);
filter->dir_opened = filter_dir_opened;
filter->dir_added = filter_dir_added;
filter->dir_deleted = filter_dir_deleted;
filter->dir_changed = filter_dir_changed;
filter->dir_closed = filter_dir_closed;
filter->file_opened = filter_file_opened;
filter->file_added = filter_file_added;
filter->file_deleted = filter_file_deleted;
filter->file_changed = filter_file_changed;
filter->file_closed = filter_file_closed;
filter->node_absent = filter_node_absent;
return filter;
}

Some files were not shown because too many files have changed in this diff Show More