]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Forward port the Apple-specific changes from [db5b7b778c] in the
authordrh <drh@noemail.net>
Mon, 10 Oct 2011 23:53:48 +0000 (23:53 +0000)
committerdrh <drh@noemail.net>
Mon, 10 Oct 2011 23:53:48 +0000 (23:53 +0000)
apple-osx-377 branch.  Fix this up so that it will compile and run on Linux.

FossilOrigin-Name: 6cb43f6c6e9d8054e00acab378b8af0d82d3084c

12 files changed:
1  2 
manifest
manifest.uuid
src/backup.c
src/main.c
src/mem1.c
src/os_unix.c
src/os_win.c
src/pager.c
src/sqlite.h.in
src/sqliteInt.h
src/test1.c
src/vdbeaux.c

diff --cc manifest
index 88d43531c2d2c2a1152c7a8ff35edc7b3d726865,f5f83fd9ddb0e2ea030326e15b9f52eaa6a38004..042043c90565a013a1d353f459cc04431ff0d75a
+++ b/manifest
@@@ -1,12 -1,12 +1,12 @@@
- C Merge\sin\sall\strunk\schanges\sthrough\sthe\s3.7.8\srelease.
- D 2011-09-19T20:32:36.507
 -C Merging\sin\scherry\spicked\sdiffs\sfor\spersist\swal,\salloc\spadding,\swal-safe\svacuum\sand\ssqlite3_file_control\sbased\slockstate\schecking
 -D 2011-10-10T22:11:44.216
++C Forward\sport\sthe\sApple-specific\schanges\sfrom\s[db5b7b778c]\sin\sthe\napple-osx-377\sbranch.\s\sFix\sthis\sup\sso\sthat\sit\swill\scompile\sand\srun\son\sLinux.
++D 2011-10-10T23:53:48.384
  F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 -F Makefile.in 8410b02448997eb43bdf0ffa482c9bc2d2624e45
 +F Makefile.in 55bbee3ada084d4aa4dab9e1e0d90a21aab8bbcf
  F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
 -F Makefile.msc 11082f65b452b908d93013292c17850378c39284
 -F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151
 +F Makefile.msc b5e917439d5ed42364173d1648aae1d418e323ea
 +F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9
  F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
 -F VERSION 3fcdd7fbe3eb282df3978fe77288544543767961
 +F VERSION f724de7326e87b7f3b0a55f16ef4b4d993680d54
  F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
  F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
  F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
@@@ -124,23 -124,23 +124,23 @@@ F src/alter.c ac80a0f31189f8b4a524ebf66
  F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
  F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
  F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
- F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3
 -F src/backup.c 1cf56cc81b035e0a9884ddac13442edefcb0cb46
++F src/backup.c 5774963f44ed38c56561033694d3a5ad516c556b
  F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
  F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
 -F src/btree.c 1870b70e376c5c9ff31e1235e4e4434212709265
 +F src/btree.c 71a65f9bbdc3c93bd0f043aa9148b751474cea5e
  F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
  F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
 -F src/build.c 5a428625d21ad409514afb40ad083bee25dd957a
 +F src/build.c 851e81f26a75abbb98bd99a7c5f10e8670d867bb
  F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
  F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 -F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
 -F src/date.c d3c11de76392ea62637bfac0f4655889fc2f5a85
 -F src/delete.c 4925f9121525fc871f5d8d13c1f7dcc91abb38bb
 -F src/expr.c ab46ab0f0c44979a8164ca31728d7d10ae5e8106
 +F src/ctime.c e3132ec65240b2e2f3d50831021eac387f27584d
 +F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3
 +F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8
 +F src/expr.c f4dcaeb8252c4b16fcdc245660f70ed366bc6cdd
  F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 -F src/fkey.c 9fabba17a4d4778dc660f0cb9d781fc86d7b9d41
 +F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c
  F src/func.c 1b9d471b632d8529e0f86b7bd2b918dcc2cb1097
 -F src/global.c c70a46f28680f8d7c097dbc0430ccf3b932e90b0
 +F src/global.c e230227de13601714b29f9363028514aada5ae2f
  F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
  F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
  F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@@@ -148,13 -148,13 +148,13 @@@ F src/insert.c 3eea5a53d2644116fb865afa
  F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
  F src/legacy.c 015826a958f690302d27e096a68d50b3657e4201
  F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
 -F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
 -F src/main.c f3d35af74fdccb20f7edb31d842006d99887cf2e
 +F src/loadext.c 99a161b27a499fc8ad40745b7b1900a26f0a5f51
- F src/main.c 242eaa584e256364f81f2aef97d3eca283d94073
++F src/main.c 4aabaa8d510c08d59595be5d83c4d630e8200982
  F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
  F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
- F src/mem1.c 46095d62b241466ef51970e592aa3a7a87e443e1
 -F src/mem1.c 1abe5a2c20d981e050504684bfdd3a126356e6d9
++F src/mem1.c c390a8fce10912a770ebe6fa031f5f463649e7ae
  F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
 -F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
 +F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
  F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
  F src/memjournal.c 0ebce851677a7ac035ba1512a7e65851b34530c6
  F src/mutex.c 6949180803ff05a7d0e2b9334a95b4fb5a00e23f
@@@ -164,13 -164,13 +164,13 @@@ F src/mutex_os2.c 882d735098c07c8c6a547
  F src/mutex_unix.c b4f4e923bb8de93ec3f251fadb50855f23df9579
  F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
  F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
 -F src/os.c 1663f3754a3da185369a121a4f417762f77880b6
 +F src/os.c 0668c16ae226cd58cef8240e5edbd0c93248739e
  F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
 -F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
 +F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
  F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
- F src/os_unix.c 6fdce4067dc5796b358bd9cf55cf5dd62d580945
- F src/os_win.c 0fc0f46c94b0385a940b0ee32992a833019a5985
- F src/pager.c 984dc40d797d8d822d6ce1d184287600d94a289f
 -F src/os_unix.c 8f60f53930d4c9e781c46d803b3534d004282442
 -F src/os_win.c daa67fe04bd162fbcc387214e9614a7faa6b90b1
 -F src/pager.c 4bee5b51c33855cd8de4094709912b000f2bccff
++F src/os_unix.c ed727d5822235e16519e82ba8bb355426381e1be
++F src/os_win.c 3fc8f4bb69dd71b2dc6b48e8d5fb411748197470
++F src/pager.c 5cafaf3833fceefd21bfa4dd2254b71461663286
  F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
  F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
  F src/pcache.c 49e718c095810c6b3334e3a6d89970aceaddefce
@@@ -180,19 -180,19 +180,19 @@@ F src/pragma.c 66661dbe8428dd3215bd4c8f
  F src/prepare.c 9d7403fe75fefa134351b41400d09ba1b189134b
  F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
  F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
 -F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
 +F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4
  F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
 -F src/select.c 75b7dd8c6a5ff9b8ec3f7ed51d31af8b30f114bc
 -F src/shell.c 0e0173b3e79d956368013e759f084caa7995ecb1
 -F src/sqlite.h.in 05e72174ea58476dc71db4bb6816f5b79a100f76
 +F src/select.c f3971442d59d06801ac3c712f2851ece8d1cdead
 +F src/shell.c 13fe2aeddc3cc90d6a273831d1f63736d1596f81
- F src/sqlite.h.in 175065018323ca082092f92873e074647d00bec2
- F src/sqlite3_private.h 1d18557420cb0cc51ff31ec0a3fcce11e5cd6f5a
++F src/sqlite.h.in 9b74f2d71c15cc9e3f78c16474e2096a707ceba5
+ F src/sqlite3_private.h e3b586e0aa329075d99be7198df9bc80c5b19e2d
 -F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
 -F src/sqliteInt.h 2f4919d0105a821f04433a181f877c8a70201f9a
 +F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93
- F src/sqliteInt.h 751564e4eb28a49d4f53f7bd2a211a48115d01d7
++F src/sqliteInt.h e9a32825290cee916e3e0939c857a13801afc700
  F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
  F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
  F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
 -F src/tclsqlite.c 5db825be61708b1a2b3f8f6e185e9b753829acef
 -F src/test1.c 1ce078b76ff2876c32b6ae4d1bbf754f704c87cb
 +F src/tclsqlite.c 3ef1dda2f1dc207c792eaadebf9d8adc44648581
- F src/test1.c 48759e7898dd7af7ae2b01de12045814583e15c6
++F src/test1.c 63a00ab722cc49025a6f675bcda39bed83663a48
  F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
  F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
  F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
@@@ -237,35 -237,34 +237,35 @@@ F src/test_vfstrace.c 0b884e06094a746da
  F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
  F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
  F src/tokenize.c c819d9f72168a035d545a5bdafe9b085b20df705
 -F src/trigger.c c836a6caac16ba96611558922106858f6ca3d6bf
 -F src/update.c 80d77311d91ebc06b27149e75701f1b3e9356622
 +F src/trigger.c 1cfb80e2290ef66ea89cb4e821caae65a02c0d56
 +F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec
  F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0
 -F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
 +F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7
  F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
 -F src/vdbe.c 80d511d7096918f4f6be6a63988a885c54dd1048
 -F src/vdbe.h 5cf09e7ee8a3f7d93bc51f196a96550786afe7a1
 -F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45
 -F src/vdbeapi.c 7f01db7d26758b2be316116f8325a0b9f0d8edd6
 -F src/vdbeaux.c cfb5207d13d0bc3d2753bba67900c462b60ecb08
 -F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
 -F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
 +F src/vdbe.c 26deb38f5bd32ebeb2cb60853a52f2bf33d71641
 +F src/vdbe.h f0725ee997db869ecae5bb70a71612aabeca7755
 +F src/vdbeInt.h 693d6ac6810298fc6b4c503cfbe3f99a240f40af
 +F src/vdbeapi.c 335435e65443f38d3073b5043e80cbbb7090c2d9
- F src/vdbeaux.c 49be7a5ce6a1b7df9ef5791133c3e4e6ab2a1ffe
++F src/vdbeaux.c 669fe607968e058ef49f7ed7846efde4fece5848
 +F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
 +F src/vdbemem.c 5e6effb96dd53d233361cbfaa3f0a43b9af689e9
 +F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
  F src/vdbetrace.c 4b92fe7355f682368203d29b2be7125cbab85e79
  F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
- F src/wal.c 92c7c876b026d5e38fab3ce332e49266ffcf8b2b
+ F src/wal.c eea77c324942f7e31ce9c3a5e6e86c4a0424fa09
  F src/wal.h e75d87752bd5df3dc4152ee2cb3b0dcd0b309e5e
  F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 -F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
 -F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199
 +F src/where.c b641d399cfd8588d0e20d9790d1582b663a732a8
 +F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
  F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
  F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
 -F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
 -F test/alter.test a3f570072b53d7c0fe463bab3f5affa8e113c487
 -F test/alter2.test 75f731508f1bf27ba09a6075c66cd02216ba464b
 -F test/alter3.test 8677e48d95536f7a6ed86a1a774744dadcc22b07
 -F test/alter4.test 1e5dd6b951e9f65ca66422edff02e56df82dd403
 +F test/all.test 52fc8dee494092031a556911d404ca30a749a30b
 +F test/alter.test 5314fc01ef51ab8af0b8890725b710ed48d4806b
 +F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
 +F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
 +F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5
  F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
 -F test/analyze.test c8cb89e8736336f1f0646c8123e6028a14c7b55e
 +F test/analyze.test 68b43c1f9cd6ffc3bbb30d27a23712b38c413eca
  F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
  F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
  F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
@@@ -964,11 -951,11 +964,11 @@@ F tool/speedtest2.tcl ee2149167303ba8e9
  F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
  F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
  F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
 -F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00
 -F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
 +F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
 +F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
  F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 -F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d
 -P aef7945c423a8338374572eeda9444866c64569b
 -R d7448c6862ea7b8b001f5bf968511903
 -U adam
 -Z 39deebc534cda2d5bd1c84327ddbee27
 +F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2
- P ffed86bf969b98d196ac50bb5e5faddecab4fc59 3e0da808d2f5b4d12046e05980ca04578f581177
- R fab0c6c716ebe505f8c308159e4b4eab
++P ade72b1874c7672ae8d62b9ebac8e4d63fee80cc db5b7b778c09c57501cb8266895a0ea4f2de7649
++R 492a1b6738940e27b5c3378a18dde5be
 +U drh
- Z 7d1fe25483dc7359b7f468acf5aa09ab
++Z 7f2d52c0164fc6fa32a2a1d8b7959b0c
diff --cc manifest.uuid
index 09073088a74790213e22381a8ecc7aa3fccbef82,1d16fcb8650fc14d7aa558bae266e91e97e9dbf5..fb06f2d6259df3057923e1df4bf96cefe66a7ce0
@@@ -1,1 -1,1 +1,1 @@@
- ade72b1874c7672ae8d62b9ebac8e4d63fee80cc
 -db5b7b778c09c57501cb8266895a0ea4f2de7649
++6cb43f6c6e9d8054e00acab378b8af0d82d3084c
diff --cc src/backup.c
index 70a782665b165981e09fb522dabf1cb9d2273a1e,322ff87af6a819ca76ad0589f081097a95e83b7c..ab2555a08052afc37c6d6d99de3e30a2855105b2
@@@ -410,106 -410,111 +410,115 @@@ int sqlite3_backup_step(sqlite3_backup 
      ** the case where the source and destination databases have the
      ** same schema version.
      */
 -    if( rc==SQLITE_DONE 
 -     && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
 -    ){
 -      int nDestTruncate;
 -  
 -      if( p->pDestDb ){
 -        sqlite3ResetInternalSchema(p->pDestDb, -1);
 +    if( rc==SQLITE_DONE ){
 +      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
 +      if( rc==SQLITE_OK ){
 +        if( p->pDestDb ){
 +          sqlite3ResetInternalSchema(p->pDestDb, -1);
 +        }
 +        if( destMode==PAGER_JOURNALMODE_WAL ){
 +          rc = sqlite3BtreeSetVersion(p->pDest, 2);
 +        }
+         }
+       
+       if( destMode==PAGER_JOURNALMODE_WAL ){
+           /* This call cannot fail. The success of the BtreeUpdateMeta()
 -                    ** method above indicates that a write transaction has been opened
 -                    ** and page 1 is already dirty. Therefore this always succeeds.
 -                    */
++          ** method above indicates that a write transaction has been opened
++          ** and page 1 is already dirty. Therefore this always succeeds.
++          */
+           TESTONLY(int rc2 =) sqlite3BtreeSetVersion(p->pDest, 2);
+           assert( rc2==SQLITE_OK );
        }
 -
 -      /* Set nDestTruncate to the final number of pages in the destination
 -      ** database. The complication here is that the destination page
 -      ** size may be different to the source page size. 
 -      **
 -      ** If the source page size is smaller than the destination page size, 
 -      ** round up. In this case the call to sqlite3OsTruncate() below will
 -      ** fix the size of the file. However it is important to call
 -      ** sqlite3PagerTruncateImage() here so that any pages in the 
 -      ** destination file that lie beyond the nDestTruncate page mark are
 -      ** journalled by PagerCommitPhaseOne() before they are destroyed
 -      ** by the file truncation.
 -      */
 -      assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
 -      assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
 -      if( pgszSrc<pgszDest ){
 -        int ratio = pgszDest/pgszSrc;
 -        nDestTruncate = (nSrcPage+ratio-1)/ratio;
 -        if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
 -          nDestTruncate--;
 -        }
 -      }else{
 -        nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
 -      }
 -      sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
 -
 -      if( pgszSrc<pgszDest ){
 -        /* If the source page-size is smaller than the destination page-size,
 -        ** two extra things may need to happen:
 -        **
 -        **   * The destination may need to be truncated, and
 +      if( rc==SQLITE_OK ){
 +        int nDestTruncate;
 +        /* Set nDestTruncate to the final number of pages in the destination
 +        ** database. The complication here is that the destination page
 +        ** size may be different to the source page size. 
          **
 -        **   * Data stored on the pages immediately following the 
 -        **     pending-byte page in the source database may need to be
 -        **     copied into the destination database.
 +        ** If the source page size is smaller than the destination page size, 
 +        ** round up. In this case the call to sqlite3OsTruncate() below will
 +        ** fix the size of the file. However it is important to call
 +        ** sqlite3PagerTruncateImage() here so that any pages in the 
 +        ** destination file that lie beyond the nDestTruncate page mark are
 +        ** journalled by PagerCommitPhaseOne() before they are destroyed
 +        ** by the file truncation.
          */
 -        const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
 -        sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
 -        i64 iOff;
 -        i64 iEnd;
 -
 -        assert( pFile );
 -        assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
 -              nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
 -           && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
 -        ));
 -
 -        /* This call ensures that all data required to recreate the original
 -        ** database has been stored in the journal for pDestPager and the
 -        ** journal synced to disk. So at this point we may safely modify
 -        ** the database file in any way, knowing that if a power failure
 -        ** occurs, the original database will be reconstructed from the 
 -        ** journal file.  */
 -        rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
 -
 -        /* Write the extra pages and truncate the database file as required. */
 -        iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
 -        for(
 -          iOff=PENDING_BYTE+pgszSrc; 
 -          rc==SQLITE_OK && iOff<iEnd; 
 -          iOff+=pgszSrc
 -        ){
 -          PgHdr *pSrcPg = 0;
 -          const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
 -          rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
 -          if( rc==SQLITE_OK ){
 -            u8 *zData = sqlite3PagerGetData(pSrcPg);
 -            rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
 +        assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
 +        assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
 +        if( pgszSrc<pgszDest ){
 +          int ratio = pgszDest/pgszSrc;
 +          nDestTruncate = (nSrcPage+ratio-1)/ratio;
 +          if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
 +            nDestTruncate--;
            }
 -          sqlite3PagerUnref(pSrcPg);
 -        }
 -        if( rc==SQLITE_OK ){
 -          rc = backupTruncateFile(pFile, iSize);
 +        }else{
 +          nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
          }
 +        sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
 +
 +        if( pgszSrc<pgszDest ){
 +          /* If the source page-size is smaller than the destination page-size,
 +          ** two extra things may need to happen:
 +          **
 +          **   * The destination may need to be truncated, and
 +          **
 +          **   * Data stored on the pages immediately following the 
 +          **     pending-byte page in the source database may need to be
 +          **     copied into the destination database.
 +          */
 +          const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
 +          sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
 +          i64 iOff;
 +          i64 iEnd;
 +
 +          assert( pFile );
 +          assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
 +                nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
 +             && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
 +          ));
 +
 +          /* This call ensures that all data required to recreate the original
 +          ** database has been stored in the journal for pDestPager and the
 +          ** journal synced to disk. So at this point we may safely modify
 +          ** the database file in any way, knowing that if a power failure
 +          ** occurs, the original database will be reconstructed from the 
 +          ** journal file.  */
 +          rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
 +
 +          /* Write the extra pages and truncate the database file as required */
 +          iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
 +          for(
 +            iOff=PENDING_BYTE+pgszSrc; 
 +            rc==SQLITE_OK && iOff<iEnd; 
 +            iOff+=pgszSrc
 +          ){
 +            PgHdr *pSrcPg = 0;
 +            const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
 +            rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
 +            if( rc==SQLITE_OK ){
 +              u8 *zData = sqlite3PagerGetData(pSrcPg);
 +              rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
 +            }
 +            sqlite3PagerUnref(pSrcPg);
 +          }
 +          if( rc==SQLITE_OK ){
 +            rc = backupTruncateFile(pFile, iSize);
 +          }
  
 -        /* Sync the database file to disk. */
 -        if( rc==SQLITE_OK ){
 -          rc = sqlite3PagerSync(pDestPager);
 +          /* Sync the database file to disk. */
 +          if( rc==SQLITE_OK ){
 +            rc = sqlite3PagerSync(pDestPager);
 +          }
 +        }else{
 +          rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
 +        }
 +    
 +        /* Finish committing the transaction to the destination database. */
 +        if( SQLITE_OK==rc
 +         && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
 +        ){
 +          rc = SQLITE_DONE;
          }
 -      }else{
 -        rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
 -      }
 -  
 -      /* Finish committing the transaction to the destination database. */
 -      if( SQLITE_OK==rc
 -       && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
 -      ){
 -        rc = SQLITE_DONE;
        }
      }
    
diff --cc src/main.c
Simple merge
diff --cc src/mem1.c
index 6b1c30afb53ab19f6144b64da9741338d1367063,43a463d44770e2d1391741facd7a97f6f4f066fb..a845b292f7243aca01b4572ce3157ca03120de9d
@@@ -32,7 -32,7 +32,6 @@@
  #define SQLITE_FREE(x) free(x)
  #define SQLITE_REALLOC(x,y) realloc((x),(y))
  
--
  #else
  
  
@@@ -60,14 -61,11 +60,22 @@@ static void *sqlite3MemMalloc(int nByte
    sqlite3_int64 *p;
    assert( nByte>0 );
    nByte = ROUND8(nByte);
-   p = SQLITE_MALLOC( nByte+8 );
++#ifndef SQLITE_MALLOCSIZE
++  p = SQLITE_MALLOC( nByte + 8 );
 +  if( p ){
 +    p[0] = nByte;
 +    p++;
 +  }else{
 +    testcase( sqlite3GlobalConfig.xLog!=0 );
 +    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
 +  }
++#else
+   p = SQLITE_MALLOC( nByte );
+   if( !p ){
+     testcase( sqlite3GlobalConfig.xLog!=0 );
+     sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
+   }
++#endif
    return (void *)p;
  }
  
@@@ -82,7 -80,6 +90,9 @@@
  static void sqlite3MemFree(void *pPrior){
    sqlite3_int64 *p = (sqlite3_int64*)pPrior;
    assert( pPrior!=0 );
++#ifndef SQLITE_MALLOCSIZE
 +  p--;
++#endif
    SQLITE_FREE(p);
  }
  
  ** or xRealloc().
  */
  static int sqlite3MemSize(void *pPrior){
++#ifndef SQLITE_MALLOCSIZE
    sqlite3_int64 *p;
    if( pPrior==0 ) return 0;
 +  p = (sqlite3_int64*)pPrior;
 +  p--;
 +  return (int)p[0];
++#else
+   return (int)SQLITE_MALLOCSIZE(pPrior);
++#endif
  }
  
  /*
@@@ -112,17 -107,13 +126,27 @@@ static void *sqlite3MemRealloc(void *pP
    sqlite3_int64 *p = (sqlite3_int64*)pPrior;
    assert( pPrior!=0 && nByte>0 );
    assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
++#ifndef SQLITE_MALLOCSIZE
 +  p--;
 +  p = SQLITE_REALLOC(p, nByte+8 );
 +  if( p ){
 +    p[0] = nByte;
 +    p++;
 +  }else{
++     testcase( sqlite3GlobalConfig.xLog!=0 );
++     sqlite3_log(SQLITE_NOMEM,
++       "failed memory resize %u to %u bytes",
++       sqlite3MemSize(pPrior), nByte);
++  }
++#else
+   p = SQLITE_REALLOC(p, nByte );
+   if( !p ){
      testcase( sqlite3GlobalConfig.xLog!=0 );
      sqlite3_log(SQLITE_NOMEM,
        "failed memory resize %u to %u bytes",
        sqlite3MemSize(pPrior), nByte);
    }
++#endif
    return (void*)p;
  }
  
diff --cc src/os_unix.c
index f38258124e9650cc1c46f2ca21fee2ebb809370e,9ec16348a5b9b38fe55fb7e48998ebbeef0cd2e3..009b79a5c82932fc902d956253893b5ef2b5285b
@@@ -1574,8 -1561,16 +1574,8 @@@ static int unixCheckReservedLock(sqlite
  ** Zero is returned if the call completes successfully, or -1 if a call
  ** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
  */
--static int unixFileLock(unixFile *pFile, struct flock *pLock){
 -  return _unixFileLock(pFile, pLock, 0);
 -}
 -
 -static int unixFileLock2(unixFile *pFile, struct flock *pLock){
 -  return _unixFileLock(pFile, pLock, 10);
 -}
 -
 -static int _unixFileLock(unixFile *pFile, struct flock *pLock, int retry) {
 -  int rc = 0;
++static int unixFileLock(unixFile *pFile, struct flock *pLock, int nRetry){
 +  int rc;
    unixInodeInfo *pInode = pFile->pInode;
    assert( unixMutexHeld() );
    assert( pInode!=0 );
        pInode->bProcessLock = 1;
        pInode->nLock++;
      }else{
++      int i = 0;                      
++      do {
++        rc = osFcntl(pFile->h, F_SETLK, pLock);
++        if( rc && nRetry ){
++           usleep(100 * (++i));
++        }
++      }while( !rc && nRetry-- );
        rc = 0;
      }
    }else{
@@@ -1737,7 -1738,7 +1744,7 @@@ static int unixLock(sqlite3_file *id, i
    ){
      lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
      lock.l_start = PENDING_BYTE;
--    if( unixFileLock(pFile, &lock) ){
++    if( unixFileLock(pFile, &lock, 0) ){
        tErrno = errno;
        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
        if( IS_LOCK_ERROR(rc) ){
      /* Now get the read-lock */
      lock.l_start = SHARED_FIRST;
      lock.l_len = SHARED_SIZE;
--    if( unixFileLock(pFile, &lock) ){
++    if( unixFileLock(pFile, &lock, 0) ){
        tErrno = errno;
        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
      }
      lock.l_start = PENDING_BYTE;
      lock.l_len = 1L;
      lock.l_type = F_UNLCK;
-     if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
 -    if( unixFileLock2(pFile, &lock) && rc==SQLITE_OK ){
++    if( unixFileLock(pFile, &lock, 10) && rc==SQLITE_OK ){
        /* This could happen with a network mount */
        tErrno = errno;
  #if OSLOCKING_CHECK_BUSY_IOERR
        lock.l_len = SHARED_SIZE;
      }
  
--    if( unixFileLock(pFile, &lock) ){
++    if( unixFileLock(pFile, &lock, 0) ){
        tErrno = errno;
        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
        if( rc!=SQLITE_BUSY ){
@@@ -1930,21 -1931,21 +1937,21 @@@ static int posixUnlock(sqlite3_file *id
      **  4:   [RRRR.]
      */
      if( eFileLock==SHARED_LOCK ){
++      int tErrno;               /* Error code from system call errors */
  
  #if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
        (void)handleNFSUnlock;
        assert( handleNFSUnlock==0 );
  #endif
  #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
 -      int tErrno;               /* Error code from system call errors */
        if( handleNFSUnlock ){
-         int tErrno;               /* Error code from system call errors */
          off_t divSize = SHARED_SIZE - 1;
          
          lock.l_type = F_UNLCK;
          lock.l_whence = SEEK_SET;
          lock.l_start = SHARED_FIRST;
          lock.l_len = divSize;
-         if( unixFileLock(pFile, &lock)==(-1) ){
 -        if( unixFileLock2(pFile, &lock)==(-1) ){
++        if( unixFileLock(pFile, &lock, 10)==(-1) ){
            tErrno = errno;
  #if OSLOCKING_CHECK_BUSY_IOERR
            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
          lock.l_whence = SEEK_SET;
          lock.l_start = SHARED_FIRST;
          lock.l_len = divSize;
-         if( unixFileLock(pFile, &lock)==(-1) ){
 -        if( unixFileLock2(pFile, &lock)==(-1) ){
++        if( unixFileLock(pFile, &lock, 10)==(-1) ){
            tErrno = errno;
 -#if OSLOCKING_CHECK_BUSY_IOERR
            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
 -#else
 -          rc = SQLITE_IOERR_UNLOCK;
 -#endif
            if( IS_LOCK_ERROR(rc) ){
              pFile->lastErrno = tErrno;
            }
          lock.l_whence = SEEK_SET;
          lock.l_start = SHARED_FIRST+divSize;
          lock.l_len = SHARED_SIZE-divSize;
-         if( unixFileLock(pFile, &lock)==(-1) ){
 -        if( unixFileLock2(pFile, &lock)==(-1) ){
++        if( unixFileLock(pFile, &lock, 10)==(-1) ){
            tErrno = errno;
  #if OSLOCKING_CHECK_BUSY_IOERR
            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
          lock.l_whence = SEEK_SET;
          lock.l_start = SHARED_FIRST;
          lock.l_len = SHARED_SIZE;
-         if( unixFileLock(pFile, &lock) ){
- #if OSLOCKING_CHECK_BUSY_IOERR
 -        if( unixFileLock2(pFile, &lock) ){
++        if( unixFileLock(pFile, &lock, 10) ){
            tErrno = errno;
+ #if OSLOCKING_CHECK_BUSY_IOERR
            rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
-           if( IS_LOCK_ERROR(rc) ){
-             pFile->lastErrno = tErrno;
-           }
  #else
            /* In theory, the call to unixFileLock() cannot fail because another
            ** process is holding an incompatible lock. If it does, this 
      lock.l_whence = SEEK_SET;
      lock.l_start = PENDING_BYTE;
      lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
-     if( unixFileLock(pFile, &lock)==0 ){
 -    if( unixFileLock2(pFile, &lock)==0 ){
++    if( unixFileLock(pFile, &lock, 10)==0 ){
        pInode->eFileLock = SHARED_LOCK;
      }else{
  #if OSLOCKING_CHECK_BUSY_IOERR
        SimulateIOErrorBenign(1);
        SimulateIOError( h=(-1) )
        SimulateIOErrorBenign(0);
-       if( unixFileLock(pFile, &lock)==0 ){
 -      if( unixFileLock2(pFile, &lock)==0 ){
++      if( unixFileLock(pFile, &lock, 10)==0 ){
          pInode->eFileLock = NO_LOCK;
        }else{
  #if OSLOCKING_CHECK_BUSY_IOERR
@@@ -3887,317 -3866,307 +3894,491 @@@ static int getDbPathForUnixFile(unixFil
  #endif
  static int isProxyLockingMode(unixFile *);
  
 -static int unixTruncateDatabase(unixFile *, int);
+ #if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
 -static int unixInvalidateSupportFiles(unixFile *, int);
++static int unixTruncateDatabase(unixFile *pFile, int bFlags) {
++  sqlite3_file *id = (sqlite3_file *)pFile;
++  int rc = SQLITE_OK;
++  void *pLock = NULL;
++  int flags = 0;
++  int corruptFileLock = 0;
++  int isCorrupt = 0;
++    
++#if SQLITE_ENABLE_DATA_PROTECTION
++  flags |= pFile->protFlags;
++#endif
++#if SQLITE_ENABLE_LOCKING_STYLE
++  if( isProxyLockingMode(pFile) ){
++    flags |= SQLITE_OPEN_AUTOPROXY;
++  }
++#endif
++  
++  rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
++  if( rc ){
++    if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
++      isCorrupt = 1;
++      rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock);
++    }
++    if( rc ){
++      return rc;
++    }
++  }
++  rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
++  if( rc==SQLITE_OK ){
++    unixInvalidateSupportFiles(pFile, 0);
++  }
++  pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
++
++
++  if( isCorrupt ){
++    sqlite3demo_superunlock_corrupt(id, corruptFileLock);
++  }else{
++    sqlite3demo_superunlock(pLock);
++  }
++  return rc;
++}
 -
++static int unixInvalidateSupportFiles(unixFile *pFile, int skipWAL) {
++  char jPath[MAXPATHLEN+9];
++  int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
++  if( zLen<MAXPATHLEN ){
++    size_t jLen;
++    const char extensions[3][9] = { "-wal", "-journal", "-shm" };
++    int j = (skipWAL ? 1 : 0);
++    for( ; j<3; j++ ){
++      
++      /* Check to see if the shm file is already opened for this pFile */
++      if( j==2 ){
++        unixEnterMutex(); /* Because pFile->pInode is shared across threads */
++        unixShmNode *pShmNode = pFile->pInode->pShmNode;
++        if( pShmNode && !pShmNode->isReadonly ){
++          struct stat sStat;
++          sqlite3_mutex_enter(pShmNode->mutex);
++          
++          if( pShmNode->h>=0 && !osFstat(pShmNode->h, &sStat) ){
++            unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4;
++            if( size>0 ){
++              bzero(pShmNode->apRegion[0], size);
++              sqlite3_mutex_leave(pShmNode->mutex);
++              unixLeaveMutex();
++              continue;
++            }
++          }
++          sqlite3_mutex_leave(pShmNode->mutex);
++        }
++        unixLeaveMutex();
++      }
++      jLen = strlcpy(&jPath[zLen], extensions[j], 9);
++      if( jLen < 9 ){
++        int jflags = (j<2) ? O_TRUNC : O_RDWR;
++        int jfd = open(jPath, jflags);
++        if( jfd==(-1) ){
++          if( errno!=ENOENT ){
++            perror(jPath);
++          }
++        } else {
++          if( j==2 ){
++            struct stat sStat;
++            if( !osFstat(jfd, &sStat) ){
++              unsigned long size = (sStat.st_size<4) ? sStat.st_size : 4;
++              if( size>0 ){
++                uint32_t zero = 0;
++                pwrite(jfd, &zero, (size_t)size, 0);
++              }
++            }
++          }
++          fsync(jfd);
++          close(jfd);
++        }
++      }
++    }
++  }
++  return SQLITE_OK;
++}
+ static int unixReplaceDatabase(unixFile *pFile, sqlite3 *srcdb) {
+   sqlite3_file *id = (sqlite3_file *)pFile;
+   Btree *pSrcBtree = NULL;
+   sqlite3_file *src_file = NULL;
+   unixFile *pSrcFile = NULL;
+   char srcWalPath[MAXPATHLEN+5];
+   int srcWalFD = -1;
+   int rc = SQLITE_OK;
+   void *pLock = NULL;
+   int flags = 0;
+   sqlite3 *srcdb2 = NULL;
+   copyfile_state_t s;
+   int corruptSrcFileLock = 0;
+   int corruptDstFileLock = 0;
+   int isSrcCorrupt = 0;
+   int isDstCorrupt = 0;
+   
+   if( !sqlite3SafetyCheckOk(srcdb) ){
+     return SQLITE_MISUSE;
+   }
+     
+ #if SQLITE_ENABLE_DATA_PROTECTION
+   flags |= pFile->protFlags;
+ #endif
+ #if SQLITE_ENABLE_LOCKING_STYLE
+   if( isProxyLockingMode(pFile) ){
+     flags |= SQLITE_OPEN_AUTOPROXY;
+   }
+ #endif
+   
+   rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
+   if( rc ){
+     if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
+       isDstCorrupt = 1;
+       rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock);
+     }
+     if( rc ){
+       return rc;
+     }
+   }
+   /* get the src file descriptor adhering to the db struct access rules 
+    ** this code is modeled after sqlite3_file_control() in main.c
+    */ 
+   sqlite3_mutex_enter(srcdb->mutex);
+   if( srcdb->nDb>0 ){
+     pSrcBtree = srcdb->aDb[0].pBt;
+   }
+   if( pSrcBtree ){
+     Pager *pSrcPager;
+     sqlite3BtreeEnter(pSrcBtree);
+     pSrcPager = sqlite3BtreePager(pSrcBtree);
+     assert( pSrcPager!=0 );
+     src_file = sqlite3PagerFile(pSrcPager);
+     assert( src_file!=0 );
+     if( src_file->pMethods ){
+       int srcFlags = 0;
+       pSrcFile = (unixFile *)src_file;
+       /* wal mode db cannot be opened readonly */
+       if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) {
+         srcFlags = SQLITE_OPEN_READWRITE;
+       } else {
+         srcFlags = SQLITE_OPEN_READONLY;
+       }
+ #if SQLITE_ENABLE_DATA_PROTECTION
+       srcFlags |= pSrcFile->protFlags;
+ #endif
+ #if SQLITE_ENABLE_LOCKING_STYLE
+       if( isProxyLockingMode(pSrcFile) ){
+         srcFlags |= SQLITE_OPEN_AUTOPROXY;
+       }
+ #endif
+       rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0);
+       if( rc==SQLITE_OK ){
+         /* start a deferred transaction and read to establish a read lock */
+         rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0);
+         if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
+           isSrcCorrupt = 1;
+           rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock);
+         }
+       }
+     }
+   }
+   if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){
+     rc = SQLITE_INTERNAL;
+   }
+   if( rc!=SQLITE_OK ){
+     goto end_replace_database;
+   }
+   /* both databases are locked appropriately, copy the src wal journal if 
+    ** one exists and then the actual database file
+    */
+   strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5);
+   strlcat(srcWalPath, "-wal", MAXPATHLEN+5);
+   srcWalFD = open(srcWalPath, O_RDONLY);
+   if( !(srcWalFD<0) ){
+     char dstWalPath[MAXPATHLEN+5];
+     int dstWalFD = -1;
+     strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5);
+     strlcat(dstWalPath, "-wal", MAXPATHLEN+5);
+     dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
+     if( !(dstWalFD<0) ){
+       s = copyfile_state_alloc();
+       lseek(srcWalFD, 0, SEEK_SET);
+       lseek(dstWalFD, 0, SEEK_SET);
+       if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){
+         int err=errno;
+         switch(err) {
+           case ENOMEM:
+             rc = SQLITE_NOMEM;
+             break;
+           default:
+             pFile->lastErrno = err;
+             rc = SQLITE_IOERR;
+         }
+       }
+       copyfile_state_free(s);
+       close(dstWalFD);
+     }
+     close(srcWalFD);
+   }
+   if( rc==SQLITE_OK ){
+     /* before we copy, ensure that the file change counter will be modified */
+     uint32_t srcChange = 0;
+     uint32_t dstChange = 0;
+     pread(pSrcFile->h, &srcChange, 4, 24);
+     pread(pFile->h, &dstChange, 4, 24);
+     
+     /* copy the actual database */
+     s = copyfile_state_alloc();
+     lseek(pSrcFile->h, 0, SEEK_SET);
+     lseek(pFile->h, 0, SEEK_SET);
+     if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
+       int err=errno;
+       switch(err) {
+         case ENOMEM:
+           rc = SQLITE_NOMEM;
+           break;
+         default:
+           pFile->lastErrno = err;
+           rc = SQLITE_IOERR;
+       }
+     }
+     copyfile_state_free(s);
+     
+     if (srcChange == dstChange) {
+       /* modify the change counter to force page zero to be reloaded */
+       dstChange ++;
+       pwrite(pFile->h, &dstChange, 4, 24);
+     }
+   }
+   if( isSrcCorrupt ){
+     sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock);
+   }else{
+     /* done with the source db so end the transaction */
+     sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0);
+   }
+   /* zero out any old journal clutter */
+   if( rc==SQLITE_OK ){
+     int skipWAL = (srcWalFD<0)?0:1;
+     unixInvalidateSupportFiles(pFile, skipWAL);
+   }
+   
+ end_replace_database:
+   if( pSrcBtree ){
+     sqlite3_close(srcdb2);
+     sqlite3BtreeLeave(pSrcBtree);
+   }
+   sqlite3_mutex_leave(srcdb->mutex);
+   if( isDstCorrupt ){
+     sqlite3demo_superunlock_corrupt(id, corruptDstFileLock);
+   }else{
+     sqlite3demo_superunlock(pLock);
+   }
+   return rc;
+ }
 -static int unixLockstatePid(unixFile *, pid_t, int *);
 -
 -#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
 -                               
+ #define SQLITE_FILE_HEADER_LEN 16
+ #include "btreeInt.h"
+ /* Check for a conflicting lock.  If one is found, print an this
+  ** on standard output using the format string given and return 1.
+  ** If there are no conflicting locks, return 0.
+  */
+ static int unixIsLocked(
+   pid_t pid,            /* PID to test for lock owner */
+   int h,                /* File descriptor to check */
+   int type,             /* F_RDLCK or F_WRLCK */
+   unsigned int iOfst,   /* First byte of the lock */
+   unsigned int iCnt,    /* Number of bytes in the lock range */
+   const char *zType     /* Type of lock */
+ ){
+   struct flock lk;
+   int err;
+   
+   memset(&lk, 0, sizeof(lk));
+   lk.l_type = type;
+   lk.l_whence = SEEK_SET;
+   lk.l_start = iOfst;
+   lk.l_len = iCnt;
+   
+   if( pid!=SQLITE_LOCKSTATE_ANYPID ){
+ #ifndef F_GETLKPID
+ # warning F_GETLKPID undefined, _sqlite3_lockstate falling back to F_GETLK
+     err = fcntl(h, F_GETLK, &lk);
+ #else
+     lk.l_pid = pid;
+     err = fcntl(h, F_GETLKPID, &lk);
+ #endif
+   }else{
+     err = fcntl(h, F_GETLK, &lk);
+   }
+   
+   if( err==(-1) ){
+     fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
+     return -1;
+   }
+   
+   if( lk.l_type!=F_UNLCK && (pid==SQLITE_LOCKSTATE_ANYPID || lk.l_pid==pid) ){
+ #ifdef SQLITE_DEBUG
+     fprintf(stderr, "%s lock held by %d\n", zType, (int)lk.l_pid);
+ #endif
+     return 1;
+   } 
+   return 0;
+ }
 -** Information and control of an open file handle.
+ /*
 -static int unixFileControl(sqlite3_file *id, int op, void *pArg){
 -  unixFile *pFile = (unixFile*)id;
 -  switch( op ){
 -    case SQLITE_FCNTL_LOCKSTATE: {
 -      *(int*)pArg = pFile->eFileLock;
 -      return SQLITE_OK;
 -    }
 -    case SQLITE_FCNTL_LAST_ERRNO: {
 -      *(int*)pArg = pFile->lastErrno;
 -      return SQLITE_OK;
 -    }
 -    case SQLITE_FCNTL_CHUNK_SIZE: {
 -      pFile->szChunk = *(int *)pArg;
 -      return SQLITE_OK;
 -    }
 -    case SQLITE_FCNTL_SIZE_HINT: {
 -      return fcntlSizeHint(pFile, *(i64 *)pArg);
 -    }
 -    case SQLITE_FCNTL_PERSIST_WAL: {
 -      int bPersist = *(int*)pArg;
 -      if( bPersist<0 ){
 -        *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
 -      }else if( bPersist==0 ){
 -        pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
 -      }else{
 -        pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
 -      }
 -      return SQLITE_OK;
 -    }
 -#ifndef NDEBUG
 -    /* The pager calls this method to signal that it has done
 -    ** a rollback and that the database is therefore unchanged and
 -    ** it hence it is OK for the transaction change counter to be
 -    ** unchanged.
 -    */
 -    case SQLITE_FCNTL_DB_UNCHANGED: {
 -      ((unixFile*)id)->dbUpdate = 0;
 -      return SQLITE_OK;
 -    }
 -#endif
 -#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
 -    case SQLITE_FCNTL_SET_LOCKPROXYFILE:
 -    case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
 -      return proxyFileControl(id,op,pArg);
 -    }
 -#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
 -#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
 -    case SQLITE_FCNTL_TRUNCATE_DATABASE: {
 -      return unixTruncateDatabase(pFile, (pArg ? (*(int *)pArg) : 0));
 -    }
 -    case SQLITE_FCNTL_REPLACE_DATABASE: {
 -      return unixReplaceDatabase(pFile, (sqlite3 *)pArg);
 -    }
 -    case SQLITE_FCNTL_LOCKSTATE_PID: {
 -      LockstatePID *pLockstate;
 -      int rc;
 -      
 -      if( pArg==NULL ){
 -        return SQLITE_MISUSE;
 -      }
 -      pLockstate = (LockstatePID *)pArg;
 -      rc = unixLockstatePid(pFile, pLockstate->pid, &(pLockstate->state));
 -      return rc;
++** This test only works for lock testing on unix/posix VFS.
++** Adapted from tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
+ */
++static int unixLockstatePid(unixFile *pFile, pid_t pid, int *pLockstate){
++  int hDb;        /* File descriptor for the open database file */
++  int hShm = -1;  /* File descriptor for WAL shared-memory file */
++  ssize_t got;    /* Bytes read from header */
++  int isWal;                 /* True if in WAL mode */
++  int nLock = 0;             /* Number of locks held */
++  unsigned char aHdr[100];   /* Database header */
++  
++  assert(pLockstate);
++  
++  /* make sure we are dealing with a database file */
++  hDb = pFile->h;
++  if( hDb<0 ){
++    *pLockstate = SQLITE_LOCKSTATE_ERROR;
++    return SQLITE_ERROR;
++  }
++  assert( (strlen(SQLITE_FILE_HEADER)+1)==SQLITE_FILE_HEADER_LEN );
++  got = pread(hDb, aHdr, 100, 0);
++  if( got<0 ){
++    *pLockstate = SQLITE_LOCKSTATE_ERROR;
++    return SQLITE_ERROR;
++  }
++  if( got!=100 || memcmp(aHdr, SQLITE_FILE_HEADER, SQLITE_FILE_HEADER_LEN)!=0 ){
++    *pLockstate = SQLITE_LOCKSTATE_NOTADB;
++    return SQLITE_NOTADB;
++  }
++  
++  /* First check for an exclusive lock */
++  nLock += unixIsLocked(pid, hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE");
++  isWal = aHdr[18]==2;
++  if( nLock==0 && isWal==0 ){
++    /* Rollback mode */
++    nLock += unixIsLocked(pid, hDb, F_WRLCK, PENDING_BYTE, SHARED_SIZE+2, "PENDING|RESERVED|SHARED");
++  }
++  if( nLock==0 && isWal!=0 ){
++    /* lookup the file descriptor for the shared memory file if we have it open in this process */
++    unixEnterMutex(); /* Because pFile->pInode is shared across threads */
++    unixShmNode *pShmNode = pFile->pInode->pShmNode;
++    if( pShmNode ){
++      sqlite3_mutex_enter(pShmNode->mutex);
++      
++      hShm = pShmNode->h;
++      if( hShm >= 0){
++        if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ||
++           unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){
++          nLock = 1;
++        }
++      }
++      
++      sqlite3_mutex_leave(pShmNode->mutex);
++    } 
++    
++    if( hShm<0 ){
++      /* the shared memory file isn't open in this process space, open our own FD */
++      char zShm[MAXPATHLEN];
++      
++      /* WAL mode */
++      strlcpy(zShm, pFile->zPath, MAXPATHLEN);
++      strlcat(zShm, "-shm", MAXPATHLEN);
++      hShm = open(zShm, O_RDONLY, 0);
++      if( hShm<0 ){
++        *pLockstate = SQLITE_LOCKSTATE_OFF;
++        unixLeaveMutex();
++        return SQLITE_OK;
++      }
++      if( unixIsLocked(pid, hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ||
++         unixIsLocked(pid, hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE") ){
++        nLock = 1;
++      }
++      close(hShm);
++    }
++    unixLeaveMutex();
++  }
++  if( nLock>0 ){
++    *pLockstate = SQLITE_LOCKSTATE_ON;
++  } else {
++    *pLockstate = SQLITE_LOCKSTATE_OFF;
++  }
++  return SQLITE_OK;
++}
++
++#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
++
++
 +/*
 +** Information and control of an open file handle.
 +*/
 +static int unixFileControl(sqlite3_file *id, int op, void *pArg){
 +  unixFile *pFile = (unixFile*)id;
 +  switch( op ){
 +    case SQLITE_FCNTL_LOCKSTATE: {
 +      *(int*)pArg = pFile->eFileLock;
 +      return SQLITE_OK;
 +    }
 +    case SQLITE_LAST_ERRNO: {
 +      *(int*)pArg = pFile->lastErrno;
 +      return SQLITE_OK;
 +    }
 +    case SQLITE_FCNTL_CHUNK_SIZE: {
 +      pFile->szChunk = *(int *)pArg;
 +      return SQLITE_OK;
 +    }
 +    case SQLITE_FCNTL_SIZE_HINT: {
 +      int rc;
 +      SimulateIOErrorBenign(1);
 +      rc = fcntlSizeHint(pFile, *(i64 *)pArg);
 +      SimulateIOErrorBenign(0);
 +      return rc;
 +    }
 +    case SQLITE_FCNTL_PERSIST_WAL: {
 +      int bPersist = *(int*)pArg;
 +      if( bPersist<0 ){
 +        *(int*)pArg = (pFile->ctrlFlags & UNIXFILE_PERSIST_WAL)!=0;
 +      }else if( bPersist==0 ){
 +        pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
 +      }else{
 +        pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
 +      }
 +      return SQLITE_OK;
 +    }
 +#ifndef NDEBUG
 +    /* The pager calls this method to signal that it has done
 +    ** a rollback and that the database is therefore unchanged and
 +    ** it hence it is OK for the transaction change counter to be
 +    ** unchanged.
 +    */
 +    case SQLITE_FCNTL_DB_UNCHANGED: {
 +      ((unixFile*)id)->dbUpdate = 0;
 +      return SQLITE_OK;
      }
-     case SQLITE_SET_LOCKPROXYFILE:
-     case SQLITE_GET_LOCKPROXYFILE: {
 +#endif
 +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-     case SQLITE_TRUNCATE_DATABASE: {
-       unixFile *pFile = (unixFile*)id;
-       int rc = SQLITE_OK;
-       void *pLock = NULL;
-       int flags = 0;
-       int corruptFileLock = 0;
-       int isCorrupt = 0;
- #if SQLITE_ENABLE_DATA_PROTECTION
-       flags |= pFile->protFlags;
- #endif
- #if SQLITE_ENABLE_LOCKING_STYLE
-       if( isProxyLockingMode(pFile) ){
-         flags |= SQLITE_OPEN_AUTOPROXY;
-       }
- #endif
-       
-       rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
-       if( rc ){
-         if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
-           isCorrupt = 1;
-           rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptFileLock);
-         }
-         if( rc ){
-           return rc;
-         }
-       }
-       rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
-       if( rc==SQLITE_OK ){
-         char jPath[MAXPATHLEN+9];
-         int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
-         if( zLen<MAXPATHLEN ){
-           size_t jLen;
-           const char extensions[2][9] = { "-wal", "-journal" /*, "-shm" */ };
-           int j = 0;
-           for( j=0; j<2; j++ ){
-             jLen = strlcpy(&jPath[zLen], extensions[j], 9);
-             if( jLen < 9 ){
-               int jfd = open(jPath, O_TRUNC);
-               if( jfd==(-1) ){
-                 if ( errno!=ENOENT ){
-                   perror(jPath);
-                 }
-               } else {
-                 fsync(jfd);
-                 close(jfd);
-               }
-             }
-           }
-         }
-         pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
-       }
-       if( isCorrupt ){
-         sqlite3demo_superunlock_corrupt(id, corruptFileLock);
-       }else{
-         sqlite3demo_superunlock(pLock);
-       }
-       return rc;
++    case SQLITE_FCNTL_SET_LOCKPROXYFILE:
++    case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
 +      return proxyFileControl(id,op,pArg);
 +    }
 +#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
 +#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
-     case SQLITE_REPLACE_DATABASE: {
-       unixFile *pFile = (unixFile*)id;
-       sqlite3 *srcdb = (sqlite3 *)pArg;
-       Btree *pSrcBtree = NULL;
-       sqlite3_file *src_file = NULL;
-       unixFile *pSrcFile = NULL;
-       char srcWalPath[MAXPATHLEN+5];
-       int srcWalFD = -1;
-       int rc = SQLITE_OK;
-       void *pLock = NULL;
-       int flags = 0;
-       sqlite3 *srcdb2 = NULL;
-       copyfile_state_t s;
-       int corruptSrcFileLock = 0;
-       int corruptDstFileLock = 0;
-       int isSrcCorrupt = 0;
-       int isDstCorrupt = 0;
-       if( !sqlite3SafetyCheckOk(srcdb) ){
++    case SQLITE_FCNTL_TRUNCATE_DATABASE: {
++      return unixTruncateDatabase(pFile, (pArg ? (*(int *)pArg) : 0));
 +    }
++    case SQLITE_FCNTL_REPLACE_DATABASE: {
++      return unixReplaceDatabase(pFile, (sqlite3 *)pArg);
++    }
++    case SQLITE_FCNTL_LOCKSTATE_PID: {
++      LockstatePID *pLockstate;
++      int rc;
 +      
-       
- #if SQLITE_ENABLE_DATA_PROTECTION
-       flags |= pFile->protFlags;
- #endif
- #if SQLITE_ENABLE_LOCKING_STYLE
-       if( isProxyLockingMode(pFile) ){
-         flags |= SQLITE_OPEN_AUTOPROXY;
-       }
- #endif
-       
-       rc = sqlite3demo_superlock(pFile->zPath, 0, flags, 0, 0, &pLock);
-       if( rc ){
-         if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
-           isDstCorrupt = 1;
-           rc = sqlite3demo_superlock_corrupt(id, SQLITE_LOCK_EXCLUSIVE, &corruptDstFileLock);
-         }
-         if( rc ){
-           return rc;
-         }
-       }
-       /* get the src file descriptor adhering to the db struct access rules 
-        ** this code is modeled after sqlite3_file_control() in main.c
-        */ 
-       sqlite3_mutex_enter(srcdb->mutex);
-       if( srcdb->nDb>0 ){
-         pSrcBtree = srcdb->aDb[0].pBt;
-       }
-       if( pSrcBtree ){
-         Pager *pSrcPager;
-         sqlite3BtreeEnter(pSrcBtree);
-         pSrcPager = sqlite3BtreePager(pSrcBtree);
-         assert( pSrcPager!=0 );
-         src_file = sqlite3PagerFile(pSrcPager);
-         assert( src_file!=0 );
-         if( src_file->pMethods ){
-           int srcFlags = 0;
-           pSrcFile = (unixFile *)src_file;
-           /* wal mode db cannot be opened readonly */
-           if ((pSrcFile->openFlags & O_RDWR) == O_RDWR) {
-             srcFlags = SQLITE_OPEN_READWRITE;
-           } else {
-             srcFlags = SQLITE_OPEN_READONLY;
-           }
- #if SQLITE_ENABLE_DATA_PROTECTION
-           srcFlags |= pSrcFile->protFlags;
- #endif
- #if SQLITE_ENABLE_LOCKING_STYLE
-           if( isProxyLockingMode(pSrcFile) ){
-             srcFlags |= SQLITE_OPEN_AUTOPROXY;
-           }
- #endif
-           rc = sqlite3_open_v2(pSrcFile->zPath, &srcdb2, srcFlags, 0);
-           if( rc==SQLITE_OK ){
-             /* start a deferred transaction and read to establish a read lock */
-             rc = sqlite3_exec(srcdb2, "BEGIN DEFERRED; PRAGMA schema_version", 0, 0, 0);
-             if( rc==SQLITE_CORRUPT || rc==SQLITE_NOTADB ){
-               isSrcCorrupt = 1;
-               rc = sqlite3demo_superlock_corrupt(src_file, SQLITE_LOCK_SHARED, &corruptSrcFileLock);
-             }
-           }
-         }
-       }
-       if( !srcdb2 || pSrcFile==NULL || pSrcFile->h<0){
-         rc = SQLITE_INTERNAL;
-       }
-       if( rc!=SQLITE_OK ){
-         goto end_replace_database;
-       }
-       /* both databases are locked appropriately, copy the src wal journal if 
-       ** one exists and then the actual database file
-       */
-       strlcpy(srcWalPath, pSrcFile->zPath, MAXPATHLEN+5);
-       strlcat(srcWalPath, "-wal", MAXPATHLEN+5);
-       srcWalFD = open(srcWalPath, O_RDONLY);
-       if( !(srcWalFD<0) ){
-         char dstWalPath[MAXPATHLEN+5];
-         int dstWalFD = -1;
-         strlcpy(dstWalPath, pFile->zPath, MAXPATHLEN+5);
-         strlcat(dstWalPath, "-wal", MAXPATHLEN+5);
-         dstWalFD = open(dstWalPath, O_RDWR|O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
-         if( !(dstWalFD<0) ){
-           s = copyfile_state_alloc();
-           lseek(srcWalFD, 0, SEEK_SET);
-           lseek(dstWalFD, 0, SEEK_SET);
-           if( fcopyfile(srcWalFD, dstWalFD, s, COPYFILE_ALL) ){
-             int err=errno;
-             switch(err) {
-               case ENOMEM:
-                 rc = SQLITE_NOMEM;
-                 break;
-               default:
-                 pFile->lastErrno = err;
-                 rc = SQLITE_IOERR;
-             }
-           }
-           copyfile_state_free(s);
-           close(dstWalFD);
-         }
-         close(srcWalFD);
-       }
-       if( rc==SQLITE_OK ){
-         /* before we copy, ensure that the file change counter will be modified */
-         uint32_t srcChange = 0;
-         uint32_t dstChange = 0;
-         pread(pSrcFile->h, &srcChange, 4, 24);
-         pread(pFile->h, &dstChange, 4, 24);
-         
-         /* copy the actual database */
-         s = copyfile_state_alloc();
-         lseek(pSrcFile->h, 0, SEEK_SET);
-         lseek(pFile->h, 0, SEEK_SET);
-         if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
-           int err=errno;
-           switch(err) {
-             case ENOMEM:
-               rc = SQLITE_NOMEM;
-               break;
-             default:
-               pFile->lastErrno = err;
-               rc = SQLITE_IOERR;
-           }
-         }
-         copyfile_state_free(s);
-         
-         if (srcChange == dstChange) {
-           /* modify the change counter to force page zero to be reloaded */
-           dstChange ++;
-           pwrite(pFile->h, &dstChange, 4, 24);
-         }
-       }
-       if( isSrcCorrupt ){
-         sqlite3demo_superunlock_corrupt(src_file, corruptSrcFileLock);
-       }else{
-         /* done with the source db so end the transaction */
-         sqlite3_exec(srcdb2, "COMMIT", 0, 0, 0);
-       }
-       /* zero out any old journal clutter */
-       if( rc==SQLITE_OK ){
-         char jPath[MAXPATHLEN+9];
-         int zLen = strlcpy(jPath, pFile->zPath, MAXPATHLEN+9);
-         if( zLen<MAXPATHLEN ){
-           size_t jLen;
-           const char extensions[2][9] = { "-wal", "-journal" /* "-shm" */ };
-           int j = (srcWalFD<0)?0:1; /* skip the wal if we replaced it */
-           for( ; j<2; j++ ){
-             jLen = strlcpy(&jPath[zLen], extensions[j], 9);
-             if( jLen < 9 ){
-               int jfd = open(jPath, O_TRUNC);
-               if( jfd==(-1) ){
-                 if ( errno!=ENOENT ){
-                   perror(jPath);
-                 }
-               } else {
-                 fsync(jfd);
-                 close(jfd);
-               }
-             }
-           }
-         }
-         pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
-       }
-       
-     end_replace_database:
-       if( pSrcBtree ){
-         sqlite3_close(srcdb2);
-         sqlite3BtreeLeave(pSrcBtree);
-       }
-       sqlite3_mutex_leave(srcdb->mutex);
-       if( isDstCorrupt ){
-         sqlite3demo_superunlock_corrupt(id, corruptDstFileLock);
-       }else{
-         sqlite3demo_superunlock(pLock);
-       }
++      if( pArg==NULL ){
 +        return SQLITE_MISUSE;
 +      }
++      pLockstate = (LockstatePID *)pArg;
++      rc = unixLockstatePid(pFile, pLockstate->pid, &(pLockstate->state));
 +      return rc;
 +    }
++      
  #endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
      case SQLITE_FCNTL_SYNC_OMITTED: {
        return SQLITE_OK;  /* A no-op */
diff --cc src/os_win.c
index 33ca96c92c283b899abae823f3188269ab3b00fc,88db683dbc7e3ae16b696ac95e9422bebf73b676..f91a6a5c2f6d2a551cf843fe7ebb30cdd55f7b2f
@@@ -1613,30 -1292,21 +1613,39 @@@ static int winFileControl(sqlite3_file 
        return SQLITE_OK;
      }
      case SQLITE_FCNTL_SIZE_HINT: {
 -      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
 -      SimulateIOErrorBenign(1);
 -      winTruncate(id, sz);
 -      SimulateIOErrorBenign(0);
 +      if( pFile->szChunk>0 ){
 +        sqlite3_int64 oldSz;
 +        int rc = winFileSize(id, &oldSz);
 +        if( rc==SQLITE_OK ){
 +          sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
 +          if( newSz>oldSz ){
 +            SimulateIOErrorBenign(1);
 +            rc = winTruncate(id, newSz);
 +            SimulateIOErrorBenign(0);
 +          }
 +        }
 +        return rc;
 +      }
 +      return SQLITE_OK;
 +    }
 +    case SQLITE_FCNTL_PERSIST_WAL: {
 +      int bPersist = *(int*)pArg;
 +      if( bPersist<0 ){
 +        *(int*)pArg = pFile->bPersistWal;
 +      }else{
 +        pFile->bPersistWal = bPersist!=0;
 +      }
        return SQLITE_OK;
      }
+     case SQLITE_FCNTL_PERSIST_WAL: {
+       int bPersist = *(int*)pArg;
+       if( bPersist<0 ){
+         *(int*)pArg = pFile->bPersistWal;
+       }else{
+         pFile->bPersistWal = bPersist!=0;
+       }
+       return SQLITE_OK;
+     }
      case SQLITE_FCNTL_SYNC_OMITTED: {
        return SQLITE_OK;
      }
diff --cc src/pager.c
Simple merge
diff --cc src/sqlite.h.in
index 952905b32d91688ef1f2744b3083cb35204b6afa,6cba1ca76a5e8229c3691dfcb9fae758f6ef8acb..c6ec1e2285da468cbce2ee5ea0255540612da67f
@@@ -767,18 -751,21 +767,22 @@@ struct sqlite3_io_methods 
  ** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
  ** WAL mode.  If the integer is -1, then it is overwritten with the current
  ** WAL persistence setting.
- ** 
 -**
  */
- #define SQLITE_FCNTL_LOCKSTATE        1
- #define SQLITE_GET_LOCKPROXYFILE      2
- #define SQLITE_SET_LOCKPROXYFILE      3
- #define SQLITE_LAST_ERRNO             4
- #define SQLITE_FCNTL_SIZE_HINT        5
- #define SQLITE_FCNTL_CHUNK_SIZE       6
- #define SQLITE_FCNTL_FILE_POINTER     7
- #define SQLITE_FCNTL_SYNC_OMITTED     8
- #define SQLITE_FCNTL_WIN32_AV_RETRY   9
- #define SQLITE_FCNTL_PERSIST_WAL     10
 -#define SQLITE_FCNTL_LOCKSTATE          1
 -#define SQLITE_FCNTL_GET_LOCKPROXYFILE  2
 -#define SQLITE_FCNTL_SET_LOCKPROXYFILE  3
 -#define SQLITE_FCNTL_LAST_ERRNO         4
 -#define SQLITE_FCNTL_SIZE_HINT          5
 -#define SQLITE_FCNTL_CHUNK_SIZE         6
 -#define SQLITE_FCNTL_FILE_POINTER       7
 -#define SQLITE_FCNTL_SYNC_OMITTED       8
 -#define SQLITE_FCNTL_PERSIST_WAL       10
++#define SQLITE_FCNTL_LOCKSTATE           1
++#define SQLITE_FCNTL_GET_LOCKPROXYFILE   2
++#define SQLITE_FCNTL_SET_LOCKPROXYFILE   3
++#define SQLITE_FCNTL_LAST_ERRNO          4
++#define SQLITE_FCNTL_SIZE_HINT           5
++#define SQLITE_FCNTL_CHUNK_SIZE          6
++#define SQLITE_FCNTL_FILE_POINTER        7
++#define SQLITE_FCNTL_SYNC_OMITTED        8
++#define SQLITE_FCNTL_WIN32_AV_RETRY      9
++#define SQLITE_FCNTL_PERSIST_WAL        10
++
+ /* deprecated names */
+ #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
+ #define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
+ #define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO
  
  /*
  ** CAPI3REF: Mutex Handle
diff --cc src/sqliteInt.h
Simple merge
diff --cc src/test1.c
index 0e8968d57a54545fcb1a597b5496589610672df2,d7b7a010da4ba8b6210cf438b99cee5666dfc5f2..a5a4a8a241c14a43ec97f1c35e2594762af3195f
@@@ -5205,7 -5210,7 +5209,6 @@@ static int path_is_local
    int objc,              /* Number of arguments */
    Tcl_Obj *CONST objv[]  /* Command arguments */
  ){
--  sqlite3 *db;
    const char *zPath;
    int nPath;
    
@@@ -5247,7 -5252,7 +5250,6 @@@ static int path_is_dos
    int objc,              /* Number of arguments */
    Tcl_Obj *CONST objv[]  /* Command arguments */
  ){
--  sqlite3 *db;
    const char *zPath;
    int nPath;
    
@@@ -6170,9 -6030,8 +6172,10 @@@ int Sqlitetest1_Init(Tcl_Interp *interp
       { "file_control_replace_test", file_control_replace_test,  0   },
  #endif 
       { "file_control_chunksize_test", file_control_chunksize_test,  0   },
 -     { "file_control_sizehint_test", file_control_sizehint_test,  0   },
 +     { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
 +     { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
 +     { "file_control_persist_wal",    file_control_persist_wal,     0   },
+      { "file_control_persist_wal",    file_control_persist_wal,     0   },
       { "sqlite3_vfs_list",           vfs_list,     0   },
       { "sqlite3_create_function_v2", test_create_function_v2, 0 },
       { "path_is_local",              path_is_local,  0   },
diff --cc src/vdbeaux.c
index 1d5f713af6a6a854d950f30d57377013b098b4e6,cf0ec69e7f032504625c7cebafe1b0452377b48f..561dd3ed82bf8b5e9fe760674a8115f9c56eea0b
@@@ -1509,8 -1507,9 +1511,10 @@@ void sqlite3VdbeMakeReady
    memset(zCsr, 0, zEnd-zCsr);
    zCsr += (zCsr - (u8*)0)&7;
    assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
 +  p->expired = 0;
  
+   p->expired = 0;
+   
    /* Memory for registers, parameters, cursor, etc, is allocated in two
    ** passes.  On the first pass, we try to reuse unused space at the 
    ** end of the opcode array.  If we are unable to satisfy all memory