Merge ^/head r286422 through r286684.
This commit is contained in:
commit
f98ee84465
@ -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 \
|
||||
|
22
UPDATING
22
UPDATING
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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/).
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
73
contrib/apr/configure
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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() */
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) "." \
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
20
contrib/sqlite3/configure
vendored
20
contrib/sqlite3/configure
vendored
@ -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\\"
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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; \
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
2521
contrib/subversion/configure
vendored
2521
contrib/subversion/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -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))'`"
|
||||
|
@ -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"}
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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).
|
||||
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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'. */
|
||||
|
@ -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
|
||||
|
@ -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(©root_rev, ©root_path,
|
||||
child->node));
|
||||
SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev, pool));
|
||||
SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, FALSE, pool));
|
||||
SVN_ERR(get_dag(©root_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(©root_root, root->fs,
|
||||
copyroot_rev, pool));
|
||||
SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path,
|
||||
FALSE, pool));
|
||||
SVN_ERR(get_dag(©root_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(©from_rev, node));
|
||||
SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©from_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(©root_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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 *) ¬_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));
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 "
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user