| | @@ -1212,10 +1212,14 @@ |
| 1212 | 1212 | ++rv; |
| 1213 | 1213 | } |
| 1214 | 1214 | return rv; |
| 1215 | 1215 | } |
| 1216 | 1216 | |
| 1217 | +/* An fgets() equivalent, using Win32 file API for actual input. |
| 1218 | +** Input ends when given buffer is filled or a newline is read. |
| 1219 | +** If the FILE object is in text mode, swallows 0x0D. (ASCII CR) |
| 1220 | +*/ |
| 1217 | 1221 | SQLITE_INTERNAL_LINKAGE char * |
| 1218 | 1222 | cfGets(char *cBuf, int n, FILE *pf){ |
| 1219 | 1223 | int nci = 0; |
| 1220 | 1224 | struct FileAltIds fai = altIdsOfFile(pf); |
| 1221 | 1225 | int fmode = _setmode(fai.fd, _O_BINARY); |
| | @@ -1222,11 +1226,14 @@ |
| 1222 | 1226 | BOOL eatCR = (fmode & _O_TEXT)!=0; |
| 1223 | 1227 | _setmode(fai.fd, fmode); |
| 1224 | 1228 | while( nci < n-1 ){ |
| 1225 | 1229 | DWORD nr; |
| 1226 | 1230 | if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break; |
| 1227 | | - if( nr>0 && (!eatCR || cBuf[nci]!='\r') ) nci += nr; |
| 1231 | + if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){ |
| 1232 | + nci += nr; |
| 1233 | + if( cBuf[nci-nr]=='\n' ) break; |
| 1234 | + } |
| 1228 | 1235 | } |
| 1229 | 1236 | if( nci < n ) cBuf[nci] = 0; |
| 1230 | 1237 | return (nci>0)? cBuf : 0; |
| 1231 | 1238 | } |
| 1232 | 1239 | # else |
| | @@ -3783,10 +3790,422 @@ |
| 3783 | 3790 | } |
| 3784 | 3791 | return rc; |
| 3785 | 3792 | } |
| 3786 | 3793 | |
| 3787 | 3794 | /************************* End ../ext/misc/shathree.c ********************/ |
| 3795 | +/************************* Begin ../ext/misc/sha1.c ******************/ |
| 3796 | +/* |
| 3797 | +** 2017-01-27 |
| 3798 | +** |
| 3799 | +** The author disclaims copyright to this source code. In place of |
| 3800 | +** a legal notice, here is a blessing: |
| 3801 | +** |
| 3802 | +** May you do good and not evil. |
| 3803 | +** May you find forgiveness for yourself and forgive others. |
| 3804 | +** May you share freely, never taking more than you give. |
| 3805 | +** |
| 3806 | +****************************************************************************** |
| 3807 | +** |
| 3808 | +** This SQLite extension implements functions that compute SHA1 hashes. |
| 3809 | +** Two SQL functions are implemented: |
| 3810 | +** |
| 3811 | +** sha1(X) |
| 3812 | +** sha1_query(Y) |
| 3813 | +** |
| 3814 | +** The sha1(X) function computes the SHA1 hash of the input X, or NULL if |
| 3815 | +** X is NULL. |
| 3816 | +** |
| 3817 | +** The sha1_query(Y) function evalutes all queries in the SQL statements of Y |
| 3818 | +** and returns a hash of their results. |
| 3819 | +*/ |
| 3820 | +/* #include "sqlite3ext.h" */ |
| 3821 | +SQLITE_EXTENSION_INIT1 |
| 3822 | +#include <assert.h> |
| 3823 | +#include <string.h> |
| 3824 | +#include <stdarg.h> |
| 3825 | + |
| 3826 | +/****************************************************************************** |
| 3827 | +** The Hash Engine |
| 3828 | +*/ |
| 3829 | +/* Context for the SHA1 hash */ |
| 3830 | +typedef struct SHA1Context SHA1Context; |
| 3831 | +struct SHA1Context { |
| 3832 | + unsigned int state[5]; |
| 3833 | + unsigned int count[2]; |
| 3834 | + unsigned char buffer[64]; |
| 3835 | +}; |
| 3836 | + |
| 3837 | +#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) |
| 3838 | +#define rol(x,k) SHA_ROT(x,k,32-(k)) |
| 3839 | +#define ror(x,k) SHA_ROT(x,32-(k),k) |
| 3840 | + |
| 3841 | +#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ |
| 3842 | + |(rol(block[i],8)&0x00FF00FF)) |
| 3843 | +#define blk0be(i) block[i] |
| 3844 | +#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ |
| 3845 | + ^block[(i+2)&15]^block[i&15],1)) |
| 3846 | + |
| 3847 | +/* |
| 3848 | + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 |
| 3849 | + * |
| 3850 | + * Rl0() for little-endian and Rb0() for big-endian. Endianness is |
| 3851 | + * determined at run-time. |
| 3852 | + */ |
| 3853 | +#define Rl0(v,w,x,y,z,i) \ |
| 3854 | + z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2); |
| 3855 | +#define Rb0(v,w,x,y,z,i) \ |
| 3856 | + z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2); |
| 3857 | +#define R1(v,w,x,y,z,i) \ |
| 3858 | + z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2); |
| 3859 | +#define R2(v,w,x,y,z,i) \ |
| 3860 | + z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2); |
| 3861 | +#define R3(v,w,x,y,z,i) \ |
| 3862 | + z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2); |
| 3863 | +#define R4(v,w,x,y,z,i) \ |
| 3864 | + z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2); |
| 3865 | + |
| 3866 | +/* |
| 3867 | + * Hash a single 512-bit block. This is the core of the algorithm. |
| 3868 | + */ |
| 3869 | +static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){ |
| 3870 | + unsigned int qq[5]; /* a, b, c, d, e; */ |
| 3871 | + static int one = 1; |
| 3872 | + unsigned int block[16]; |
| 3873 | + memcpy(block, buffer, 64); |
| 3874 | + memcpy(qq,state,5*sizeof(unsigned int)); |
| 3875 | + |
| 3876 | +#define a qq[0] |
| 3877 | +#define b qq[1] |
| 3878 | +#define c qq[2] |
| 3879 | +#define d qq[3] |
| 3880 | +#define e qq[4] |
| 3881 | + |
| 3882 | + /* Copy p->state[] to working vars */ |
| 3883 | + /* |
| 3884 | + a = state[0]; |
| 3885 | + b = state[1]; |
| 3886 | + c = state[2]; |
| 3887 | + d = state[3]; |
| 3888 | + e = state[4]; |
| 3889 | + */ |
| 3890 | + |
| 3891 | + /* 4 rounds of 20 operations each. Loop unrolled. */ |
| 3892 | + if( 1 == *(unsigned char*)&one ){ |
| 3893 | + Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3); |
| 3894 | + Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7); |
| 3895 | + Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11); |
| 3896 | + Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15); |
| 3897 | + }else{ |
| 3898 | + Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3); |
| 3899 | + Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7); |
| 3900 | + Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11); |
| 3901 | + Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15); |
| 3902 | + } |
| 3903 | + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); |
| 3904 | + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); |
| 3905 | + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); |
| 3906 | + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); |
| 3907 | + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); |
| 3908 | + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); |
| 3909 | + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); |
| 3910 | + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); |
| 3911 | + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); |
| 3912 | + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); |
| 3913 | + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); |
| 3914 | + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); |
| 3915 | + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); |
| 3916 | + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); |
| 3917 | + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); |
| 3918 | + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); |
| 3919 | + |
| 3920 | + /* Add the working vars back into context.state[] */ |
| 3921 | + state[0] += a; |
| 3922 | + state[1] += b; |
| 3923 | + state[2] += c; |
| 3924 | + state[3] += d; |
| 3925 | + state[4] += e; |
| 3926 | + |
| 3927 | +#undef a |
| 3928 | +#undef b |
| 3929 | +#undef c |
| 3930 | +#undef d |
| 3931 | +#undef e |
| 3932 | +} |
| 3933 | + |
| 3934 | + |
| 3935 | +/* Initialize a SHA1 context */ |
| 3936 | +static void hash_init(SHA1Context *p){ |
| 3937 | + /* SHA1 initialization constants */ |
| 3938 | + p->state[0] = 0x67452301; |
| 3939 | + p->state[1] = 0xEFCDAB89; |
| 3940 | + p->state[2] = 0x98BADCFE; |
| 3941 | + p->state[3] = 0x10325476; |
| 3942 | + p->state[4] = 0xC3D2E1F0; |
| 3943 | + p->count[0] = p->count[1] = 0; |
| 3944 | +} |
| 3945 | + |
| 3946 | +/* Add new content to the SHA1 hash */ |
| 3947 | +static void hash_step( |
| 3948 | + SHA1Context *p, /* Add content to this context */ |
| 3949 | + const unsigned char *data, /* Data to be added */ |
| 3950 | + unsigned int len /* Number of bytes in data */ |
| 3951 | +){ |
| 3952 | + unsigned int i, j; |
| 3953 | + |
| 3954 | + j = p->count[0]; |
| 3955 | + if( (p->count[0] += len << 3) < j ){ |
| 3956 | + p->count[1] += (len>>29)+1; |
| 3957 | + } |
| 3958 | + j = (j >> 3) & 63; |
| 3959 | + if( (j + len) > 63 ){ |
| 3960 | + (void)memcpy(&p->buffer[j], data, (i = 64-j)); |
| 3961 | + SHA1Transform(p->state, p->buffer); |
| 3962 | + for(; i + 63 < len; i += 64){ |
| 3963 | + SHA1Transform(p->state, &data[i]); |
| 3964 | + } |
| 3965 | + j = 0; |
| 3966 | + }else{ |
| 3967 | + i = 0; |
| 3968 | + } |
| 3969 | + (void)memcpy(&p->buffer[j], &data[i], len - i); |
| 3970 | +} |
| 3971 | + |
| 3972 | +/* Compute a string using sqlite3_vsnprintf() and hash it */ |
| 3973 | +static void hash_step_vformat( |
| 3974 | + SHA1Context *p, /* Add content to this context */ |
| 3975 | + const char *zFormat, |
| 3976 | + ... |
| 3977 | +){ |
| 3978 | + va_list ap; |
| 3979 | + int n; |
| 3980 | + char zBuf[50]; |
| 3981 | + va_start(ap, zFormat); |
| 3982 | + sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); |
| 3983 | + va_end(ap); |
| 3984 | + n = (int)strlen(zBuf); |
| 3985 | + hash_step(p, (unsigned char*)zBuf, n); |
| 3986 | +} |
| 3987 | + |
| 3988 | + |
| 3989 | +/* Add padding and compute the message digest. Render the |
| 3990 | +** message digest as lower-case hexadecimal and put it into |
| 3991 | +** zOut[]. zOut[] must be at least 41 bytes long. */ |
| 3992 | +static void hash_finish( |
| 3993 | + SHA1Context *p, /* The SHA1 context to finish and render */ |
| 3994 | + char *zOut, /* Store hex or binary hash here */ |
| 3995 | + int bAsBinary /* 1 for binary hash, 0 for hex hash */ |
| 3996 | +){ |
| 3997 | + unsigned int i; |
| 3998 | + unsigned char finalcount[8]; |
| 3999 | + unsigned char digest[20]; |
| 4000 | + static const char zEncode[] = "0123456789abcdef"; |
| 4001 | + |
| 4002 | + for (i = 0; i < 8; i++){ |
| 4003 | + finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)] |
| 4004 | + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ |
| 4005 | + } |
| 4006 | + hash_step(p, (const unsigned char *)"\200", 1); |
| 4007 | + while ((p->count[0] & 504) != 448){ |
| 4008 | + hash_step(p, (const unsigned char *)"\0", 1); |
| 4009 | + } |
| 4010 | + hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */ |
| 4011 | + for (i = 0; i < 20; i++){ |
| 4012 | + digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); |
| 4013 | + } |
| 4014 | + if( bAsBinary ){ |
| 4015 | + memcpy(zOut, digest, 20); |
| 4016 | + }else{ |
| 4017 | + for(i=0; i<20; i++){ |
| 4018 | + zOut[i*2] = zEncode[(digest[i]>>4)&0xf]; |
| 4019 | + zOut[i*2+1] = zEncode[digest[i] & 0xf]; |
| 4020 | + } |
| 4021 | + zOut[i*2]= 0; |
| 4022 | + } |
| 4023 | +} |
| 4024 | +/* End of the hashing logic |
| 4025 | +*****************************************************************************/ |
| 4026 | + |
| 4027 | +/* |
| 4028 | +** Implementation of the sha1(X) function. |
| 4029 | +** |
| 4030 | +** Return a lower-case hexadecimal rendering of the SHA1 hash of the |
| 4031 | +** argument X. If X is a BLOB, it is hashed as is. For all other |
| 4032 | +** types of input, X is converted into a UTF-8 string and the string |
| 4033 | +** is hash without the trailing 0x00 terminator. The hash of a NULL |
| 4034 | +** value is NULL. |
| 4035 | +*/ |
| 4036 | +static void sha1Func( |
| 4037 | + sqlite3_context *context, |
| 4038 | + int argc, |
| 4039 | + sqlite3_value **argv |
| 4040 | +){ |
| 4041 | + SHA1Context cx; |
| 4042 | + int eType = sqlite3_value_type(argv[0]); |
| 4043 | + int nByte = sqlite3_value_bytes(argv[0]); |
| 4044 | + char zOut[44]; |
| 4045 | + |
| 4046 | + assert( argc==1 ); |
| 4047 | + if( eType==SQLITE_NULL ) return; |
| 4048 | + hash_init(&cx); |
| 4049 | + if( eType==SQLITE_BLOB ){ |
| 4050 | + hash_step(&cx, sqlite3_value_blob(argv[0]), nByte); |
| 4051 | + }else{ |
| 4052 | + hash_step(&cx, sqlite3_value_text(argv[0]), nByte); |
| 4053 | + } |
| 4054 | + if( sqlite3_user_data(context)!=0 ){ |
| 4055 | + hash_finish(&cx, zOut, 1); |
| 4056 | + sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT); |
| 4057 | + }else{ |
| 4058 | + hash_finish(&cx, zOut, 0); |
| 4059 | + sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT); |
| 4060 | + } |
| 4061 | +} |
| 4062 | + |
| 4063 | +/* |
| 4064 | +** Implementation of the sha1_query(SQL) function. |
| 4065 | +** |
| 4066 | +** This function compiles and runs the SQL statement(s) given in the |
| 4067 | +** argument. The results are hashed using SHA1 and that hash is returned. |
| 4068 | +** |
| 4069 | +** The original SQL text is included as part of the hash. |
| 4070 | +** |
| 4071 | +** The hash is not just a concatenation of the outputs. Each query |
| 4072 | +** is delimited and each row and value within the query is delimited, |
| 4073 | +** with all values being marked with their datatypes. |
| 4074 | +*/ |
| 4075 | +static void sha1QueryFunc( |
| 4076 | + sqlite3_context *context, |
| 4077 | + int argc, |
| 4078 | + sqlite3_value **argv |
| 4079 | +){ |
| 4080 | + sqlite3 *db = sqlite3_context_db_handle(context); |
| 4081 | + const char *zSql = (const char*)sqlite3_value_text(argv[0]); |
| 4082 | + sqlite3_stmt *pStmt = 0; |
| 4083 | + int nCol; /* Number of columns in the result set */ |
| 4084 | + int i; /* Loop counter */ |
| 4085 | + int rc; |
| 4086 | + int n; |
| 4087 | + const char *z; |
| 4088 | + SHA1Context cx; |
| 4089 | + char zOut[44]; |
| 4090 | + |
| 4091 | + assert( argc==1 ); |
| 4092 | + if( zSql==0 ) return; |
| 4093 | + hash_init(&cx); |
| 4094 | + while( zSql[0] ){ |
| 4095 | + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); |
| 4096 | + if( rc ){ |
| 4097 | + char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", |
| 4098 | + zSql, sqlite3_errmsg(db)); |
| 4099 | + sqlite3_finalize(pStmt); |
| 4100 | + sqlite3_result_error(context, zMsg, -1); |
| 4101 | + sqlite3_free(zMsg); |
| 4102 | + return; |
| 4103 | + } |
| 4104 | + if( !sqlite3_stmt_readonly(pStmt) ){ |
| 4105 | + char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); |
| 4106 | + sqlite3_finalize(pStmt); |
| 4107 | + sqlite3_result_error(context, zMsg, -1); |
| 4108 | + sqlite3_free(zMsg); |
| 4109 | + return; |
| 4110 | + } |
| 4111 | + nCol = sqlite3_column_count(pStmt); |
| 4112 | + z = sqlite3_sql(pStmt); |
| 4113 | + n = (int)strlen(z); |
| 4114 | + hash_step_vformat(&cx,"S%d:",n); |
| 4115 | + hash_step(&cx,(unsigned char*)z,n); |
| 4116 | + |
| 4117 | + /* Compute a hash over the result of the query */ |
| 4118 | + while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 4119 | + hash_step(&cx,(const unsigned char*)"R",1); |
| 4120 | + for(i=0; i<nCol; i++){ |
| 4121 | + switch( sqlite3_column_type(pStmt,i) ){ |
| 4122 | + case SQLITE_NULL: { |
| 4123 | + hash_step(&cx, (const unsigned char*)"N",1); |
| 4124 | + break; |
| 4125 | + } |
| 4126 | + case SQLITE_INTEGER: { |
| 4127 | + sqlite3_uint64 u; |
| 4128 | + int j; |
| 4129 | + unsigned char x[9]; |
| 4130 | + sqlite3_int64 v = sqlite3_column_int64(pStmt,i); |
| 4131 | + memcpy(&u, &v, 8); |
| 4132 | + for(j=8; j>=1; j--){ |
| 4133 | + x[j] = u & 0xff; |
| 4134 | + u >>= 8; |
| 4135 | + } |
| 4136 | + x[0] = 'I'; |
| 4137 | + hash_step(&cx, x, 9); |
| 4138 | + break; |
| 4139 | + } |
| 4140 | + case SQLITE_FLOAT: { |
| 4141 | + sqlite3_uint64 u; |
| 4142 | + int j; |
| 4143 | + unsigned char x[9]; |
| 4144 | + double r = sqlite3_column_double(pStmt,i); |
| 4145 | + memcpy(&u, &r, 8); |
| 4146 | + for(j=8; j>=1; j--){ |
| 4147 | + x[j] = u & 0xff; |
| 4148 | + u >>= 8; |
| 4149 | + } |
| 4150 | + x[0] = 'F'; |
| 4151 | + hash_step(&cx,x,9); |
| 4152 | + break; |
| 4153 | + } |
| 4154 | + case SQLITE_TEXT: { |
| 4155 | + int n2 = sqlite3_column_bytes(pStmt, i); |
| 4156 | + const unsigned char *z2 = sqlite3_column_text(pStmt, i); |
| 4157 | + hash_step_vformat(&cx,"T%d:",n2); |
| 4158 | + hash_step(&cx, z2, n2); |
| 4159 | + break; |
| 4160 | + } |
| 4161 | + case SQLITE_BLOB: { |
| 4162 | + int n2 = sqlite3_column_bytes(pStmt, i); |
| 4163 | + const unsigned char *z2 = sqlite3_column_blob(pStmt, i); |
| 4164 | + hash_step_vformat(&cx,"B%d:",n2); |
| 4165 | + hash_step(&cx, z2, n2); |
| 4166 | + break; |
| 4167 | + } |
| 4168 | + } |
| 4169 | + } |
| 4170 | + } |
| 4171 | + sqlite3_finalize(pStmt); |
| 4172 | + } |
| 4173 | + hash_finish(&cx, zOut, 0); |
| 4174 | + sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT); |
| 4175 | +} |
| 4176 | + |
| 4177 | + |
| 4178 | +#ifdef _WIN32 |
| 4179 | + |
| 4180 | +#endif |
| 4181 | +int sqlite3_sha_init( |
| 4182 | + sqlite3 *db, |
| 4183 | + char **pzErrMsg, |
| 4184 | + const sqlite3_api_routines *pApi |
| 4185 | +){ |
| 4186 | + int rc = SQLITE_OK; |
| 4187 | + static int one = 1; |
| 4188 | + SQLITE_EXTENSION_INIT2(pApi); |
| 4189 | + (void)pzErrMsg; /* Unused parameter */ |
| 4190 | + rc = sqlite3_create_function(db, "sha1", 1, |
| 4191 | + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
| 4192 | + 0, sha1Func, 0, 0); |
| 4193 | + if( rc==SQLITE_OK ){ |
| 4194 | + rc = sqlite3_create_function(db, "sha1b", 1, |
| 4195 | + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, |
| 4196 | + (void*)&one, sha1Func, 0, 0); |
| 4197 | + } |
| 4198 | + if( rc==SQLITE_OK ){ |
| 4199 | + rc = sqlite3_create_function(db, "sha1_query", 1, |
| 4200 | + SQLITE_UTF8|SQLITE_DIRECTONLY, 0, |
| 4201 | + sha1QueryFunc, 0, 0); |
| 4202 | + } |
| 4203 | + return rc; |
| 4204 | +} |
| 4205 | + |
| 4206 | +/************************* End ../ext/misc/sha1.c ********************/ |
| 3788 | 4207 | /************************* Begin ../ext/misc/uint.c ******************/ |
| 3789 | 4208 | /* |
| 3790 | 4209 | ** 2020-04-14 |
| 3791 | 4210 | ** |
| 3792 | 4211 | ** The author disclaims copyright to this source code. In place of |
| | @@ -5075,11 +5494,11 @@ |
| 5075 | 5494 | }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){ |
| 5076 | 5495 | p->a[p->nUsed++] = y; |
| 5077 | 5496 | }else if( p->bKeepSorted ){ |
| 5078 | 5497 | int i; |
| 5079 | 5498 | i = percentBinarySearch(p, y, 0); |
| 5080 | | - if( i<p->nUsed ){ |
| 5499 | + if( i<(int)p->nUsed ){ |
| 5081 | 5500 | memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0])); |
| 5082 | 5501 | } |
| 5083 | 5502 | p->a[i] = y; |
| 5084 | 5503 | p->nUsed++; |
| 5085 | 5504 | }else{ |
| | @@ -5191,11 +5610,11 @@ |
| 5191 | 5610 | |
| 5192 | 5611 | /* Find and remove the row */ |
| 5193 | 5612 | i = percentBinarySearch(p, y, 1); |
| 5194 | 5613 | if( i>=0 ){ |
| 5195 | 5614 | p->nUsed--; |
| 5196 | | - if( i<p->nUsed ){ |
| 5615 | + if( i<(int)p->nUsed ){ |
| 5197 | 5616 | memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0])); |
| 5198 | 5617 | } |
| 5199 | 5618 | } |
| 5200 | 5619 | } |
| 5201 | 5620 | |
| | @@ -5251,11 +5670,11 @@ |
| 5251 | 5670 | sqlite3 *db, |
| 5252 | 5671 | char **pzErrMsg, |
| 5253 | 5672 | const sqlite3_api_routines *pApi |
| 5254 | 5673 | ){ |
| 5255 | 5674 | int rc = SQLITE_OK; |
| 5256 | | - int i; |
| 5675 | + unsigned int i; |
| 5257 | 5676 | #if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE) |
| 5258 | 5677 | (void)pApi; /* Unused parameter */ |
| 5259 | 5678 | #else |
| 5260 | 5679 | SQLITE_EXTENSION_INIT2(pApi); |
| 5261 | 5680 | #endif |
| | @@ -16211,10 +16630,1000 @@ |
| 16211 | 16630 | } |
| 16212 | 16631 | return rc; |
| 16213 | 16632 | } |
| 16214 | 16633 | |
| 16215 | 16634 | /************************* End ../ext/misc/stmtrand.c ********************/ |
| 16635 | +/************************* Begin ../ext/misc/vfstrace.c ******************/ |
| 16636 | +/* |
| 16637 | +** 2011 March 16 |
| 16638 | +** |
| 16639 | +** The author disclaims copyright to this source code. In place of |
| 16640 | +** a legal notice, here is a blessing: |
| 16641 | +** |
| 16642 | +** May you do good and not evil. |
| 16643 | +** May you find forgiveness for yourself and forgive others. |
| 16644 | +** May you share freely, never taking more than you give. |
| 16645 | +** |
| 16646 | +****************************************************************************** |
| 16647 | +** |
| 16648 | +** This file contains code implements a VFS shim that writes diagnostic |
| 16649 | +** output for each VFS call, similar to "strace". |
| 16650 | +** |
| 16651 | +** USAGE: |
| 16652 | +** |
| 16653 | +** This source file exports a single symbol which is the name of a |
| 16654 | +** function: |
| 16655 | +** |
| 16656 | +** int vfstrace_register( |
| 16657 | +** const char *zTraceName, // Name of the newly constructed VFS |
| 16658 | +** const char *zOldVfsName, // Name of the underlying VFS |
| 16659 | +** int (*xOut)(const char*,void*), // Output routine. ex: fputs |
| 16660 | +** void *pOutArg, // 2nd argument to xOut. ex: stderr |
| 16661 | +** int makeDefault // Make the new VFS the default |
| 16662 | +** ); |
| 16663 | +** |
| 16664 | +** Applications that want to trace their VFS usage must provide a callback |
| 16665 | +** function with this prototype: |
| 16666 | +** |
| 16667 | +** int traceOutput(const char *zMessage, void *pAppData); |
| 16668 | +** |
| 16669 | +** This function will "output" the trace messages, where "output" can |
| 16670 | +** mean different things to different applications. The traceOutput function |
| 16671 | +** for the command-line shell (see shell.c) is "fputs" from the standard |
| 16672 | +** library, which means that all trace output is written on the stream |
| 16673 | +** specified by the second argument. In the case of the command-line shell |
| 16674 | +** the second argument is stderr. Other applications might choose to output |
| 16675 | +** trace information to a file, over a socket, or write it into a buffer. |
| 16676 | +** |
| 16677 | +** The vfstrace_register() function creates a new "shim" VFS named by |
| 16678 | +** the zTraceName parameter. A "shim" VFS is an SQLite backend that does |
| 16679 | +** not really perform the duties of a true backend, but simply filters or |
| 16680 | +** interprets VFS calls before passing them off to another VFS which does |
| 16681 | +** the actual work. In this case the other VFS - the one that does the |
| 16682 | +** real work - is identified by the second parameter, zOldVfsName. If |
| 16683 | +** the 2nd parameter is NULL then the default VFS is used. The common |
| 16684 | +** case is for the 2nd parameter to be NULL. |
| 16685 | +** |
| 16686 | +** The third and fourth parameters are the pointer to the output function |
| 16687 | +** and the second argument to the output function. For the SQLite |
| 16688 | +** command-line shell, when the -vfstrace option is used, these parameters |
| 16689 | +** are fputs and stderr, respectively. |
| 16690 | +** |
| 16691 | +** The fifth argument is true (non-zero) to cause the newly created VFS |
| 16692 | +** to become the default VFS. The common case is for the fifth parameter |
| 16693 | +** to be true. |
| 16694 | +** |
| 16695 | +** The call to vfstrace_register() simply creates the shim VFS that does |
| 16696 | +** tracing. The application must also arrange to use the new VFS for |
| 16697 | +** all database connections that are created and for which tracing is |
| 16698 | +** desired. This can be done by specifying the trace VFS using URI filename |
| 16699 | +** notation, or by specifying the trace VFS as the 4th parameter to |
| 16700 | +** sqlite3_open_v2() or by making the trace VFS be the default (by setting |
| 16701 | +** the 5th parameter of vfstrace_register() to 1). |
| 16702 | +** |
| 16703 | +** |
| 16704 | +** ENABLING VFSTRACE IN A COMMAND-LINE SHELL |
| 16705 | +** |
| 16706 | +** The SQLite command line shell implemented by the shell.c source file |
| 16707 | +** can be used with this module. To compile in -vfstrace support, first |
| 16708 | +** gather this file (test_vfstrace.c), the shell source file (shell.c), |
| 16709 | +** and the SQLite amalgamation source files (sqlite3.c, sqlite3.h) into |
| 16710 | +** the working directory. Then compile using a command like the following: |
| 16711 | +** |
| 16712 | +** gcc -o sqlite3 -Os -I. -DSQLITE_ENABLE_VFSTRACE \ |
| 16713 | +** -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE \ |
| 16714 | +** -DHAVE_READLINE -DHAVE_USLEEP=1 \ |
| 16715 | +** shell.c test_vfstrace.c sqlite3.c -ldl -lreadline -lncurses |
| 16716 | +** |
| 16717 | +** The gcc command above works on Linux and provides (in addition to the |
| 16718 | +** -vfstrace option) support for FTS3 and FTS4, RTREE, and command-line |
| 16719 | +** editing using the readline library. The command-line shell does not |
| 16720 | +** use threads so we added -DSQLITE_THREADSAFE=0 just to make the code |
| 16721 | +** run a little faster. For compiling on a Mac, you'll probably need |
| 16722 | +** to omit the -DHAVE_READLINE, the -lreadline, and the -lncurses options. |
| 16723 | +** The compilation could be simplified to just this: |
| 16724 | +** |
| 16725 | +** gcc -DSQLITE_ENABLE_VFSTRACE \ |
| 16726 | +** shell.c test_vfstrace.c sqlite3.c -ldl -lpthread |
| 16727 | +** |
| 16728 | +** In this second example, all unnecessary options have been removed |
| 16729 | +** Note that since the code is now threadsafe, we had to add the -lpthread |
| 16730 | +** option to pull in the pthreads library. |
| 16731 | +** |
| 16732 | +** To cross-compile for windows using MinGW, a command like this might |
| 16733 | +** work: |
| 16734 | +** |
| 16735 | +** /opt/mingw/bin/i386-mingw32msvc-gcc -o sqlite3.exe -Os -I \ |
| 16736 | +** -DSQLITE_THREADSAFE=0 -DSQLITE_ENABLE_VFSTRACE \ |
| 16737 | +** shell.c test_vfstrace.c sqlite3.c |
| 16738 | +** |
| 16739 | +** Similar compiler commands will work on different systems. The key |
| 16740 | +** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that |
| 16741 | +** the shell.c source file will know to include the -vfstrace command-line |
| 16742 | +** option and (2) you must compile and link the three source files |
| 16743 | +** shell,c, test_vfstrace.c, and sqlite3.c. |
| 16744 | +*/ |
| 16745 | +#include <stdlib.h> |
| 16746 | +#include <string.h> |
| 16747 | +/* #include "sqlite3.h" */ |
| 16748 | + |
| 16749 | +/* |
| 16750 | +** An instance of this structure is attached to the each trace VFS to |
| 16751 | +** provide auxiliary information. |
| 16752 | +*/ |
| 16753 | +typedef struct vfstrace_info vfstrace_info; |
| 16754 | +struct vfstrace_info { |
| 16755 | + sqlite3_vfs *pRootVfs; /* The underlying real VFS */ |
| 16756 | + int (*xOut)(const char*, void*); /* Send output here */ |
| 16757 | + void *pOutArg; /* First argument to xOut */ |
| 16758 | + const char *zVfsName; /* Name of this trace-VFS */ |
| 16759 | + sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */ |
| 16760 | +}; |
| 16761 | + |
| 16762 | +/* |
| 16763 | +** The sqlite3_file object for the trace VFS |
| 16764 | +*/ |
| 16765 | +typedef struct vfstrace_file vfstrace_file; |
| 16766 | +struct vfstrace_file { |
| 16767 | + sqlite3_file base; /* Base class. Must be first */ |
| 16768 | + vfstrace_info *pInfo; /* The trace-VFS to which this file belongs */ |
| 16769 | + const char *zFName; /* Base name of the file */ |
| 16770 | + sqlite3_file *pReal; /* The real underlying file */ |
| 16771 | +}; |
| 16772 | + |
| 16773 | +/* |
| 16774 | +** Method declarations for vfstrace_file. |
| 16775 | +*/ |
| 16776 | +static int vfstraceClose(sqlite3_file*); |
| 16777 | +static int vfstraceRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); |
| 16778 | +static int vfstraceWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64); |
| 16779 | +static int vfstraceTruncate(sqlite3_file*, sqlite3_int64 size); |
| 16780 | +static int vfstraceSync(sqlite3_file*, int flags); |
| 16781 | +static int vfstraceFileSize(sqlite3_file*, sqlite3_int64 *pSize); |
| 16782 | +static int vfstraceLock(sqlite3_file*, int); |
| 16783 | +static int vfstraceUnlock(sqlite3_file*, int); |
| 16784 | +static int vfstraceCheckReservedLock(sqlite3_file*, int *); |
| 16785 | +static int vfstraceFileControl(sqlite3_file*, int op, void *pArg); |
| 16786 | +static int vfstraceSectorSize(sqlite3_file*); |
| 16787 | +static int vfstraceDeviceCharacteristics(sqlite3_file*); |
| 16788 | +static int vfstraceShmLock(sqlite3_file*,int,int,int); |
| 16789 | +static int vfstraceShmMap(sqlite3_file*,int,int,int, void volatile **); |
| 16790 | +static void vfstraceShmBarrier(sqlite3_file*); |
| 16791 | +static int vfstraceShmUnmap(sqlite3_file*,int); |
| 16792 | + |
| 16793 | +/* |
| 16794 | +** Method declarations for vfstrace_vfs. |
| 16795 | +*/ |
| 16796 | +static int vfstraceOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); |
| 16797 | +static int vfstraceDelete(sqlite3_vfs*, const char *zName, int syncDir); |
| 16798 | +static int vfstraceAccess(sqlite3_vfs*, const char *zName, int flags, int *); |
| 16799 | +static int vfstraceFullPathname(sqlite3_vfs*, const char *zName, int, char *); |
| 16800 | +static void *vfstraceDlOpen(sqlite3_vfs*, const char *zFilename); |
| 16801 | +static void vfstraceDlError(sqlite3_vfs*, int nByte, char *zErrMsg); |
| 16802 | +static void (*vfstraceDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); |
| 16803 | +static void vfstraceDlClose(sqlite3_vfs*, void*); |
| 16804 | +static int vfstraceRandomness(sqlite3_vfs*, int nByte, char *zOut); |
| 16805 | +static int vfstraceSleep(sqlite3_vfs*, int microseconds); |
| 16806 | +static int vfstraceCurrentTime(sqlite3_vfs*, double*); |
| 16807 | +static int vfstraceGetLastError(sqlite3_vfs*, int, char*); |
| 16808 | +static int vfstraceCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); |
| 16809 | +static int vfstraceSetSystemCall(sqlite3_vfs*,const char*, sqlite3_syscall_ptr); |
| 16810 | +static sqlite3_syscall_ptr vfstraceGetSystemCall(sqlite3_vfs*, const char *); |
| 16811 | +static const char *vfstraceNextSystemCall(sqlite3_vfs*, const char *zName); |
| 16812 | + |
| 16813 | +/* |
| 16814 | +** Return a pointer to the tail of the pathname. Examples: |
| 16815 | +** |
| 16816 | +** /home/drh/xyzzy.txt -> xyzzy.txt |
| 16817 | +** xyzzy.txt -> xyzzy.txt |
| 16818 | +*/ |
| 16819 | +static const char *fileTail(const char *z){ |
| 16820 | + size_t i; |
| 16821 | + if( z==0 ) return 0; |
| 16822 | + i = strlen(z)-1; |
| 16823 | + while( i>0 && z[i-1]!='/' ){ i--; } |
| 16824 | + return &z[i]; |
| 16825 | +} |
| 16826 | + |
| 16827 | +/* |
| 16828 | +** Send trace output defined by zFormat and subsequent arguments. |
| 16829 | +*/ |
| 16830 | +static void vfstrace_printf( |
| 16831 | + vfstrace_info *pInfo, |
| 16832 | + const char *zFormat, |
| 16833 | + ... |
| 16834 | +){ |
| 16835 | + va_list ap; |
| 16836 | + char *zMsg; |
| 16837 | + va_start(ap, zFormat); |
| 16838 | + zMsg = sqlite3_vmprintf(zFormat, ap); |
| 16839 | + va_end(ap); |
| 16840 | + pInfo->xOut(zMsg, pInfo->pOutArg); |
| 16841 | + sqlite3_free(zMsg); |
| 16842 | +} |
| 16843 | + |
| 16844 | +/* |
| 16845 | +** Try to convert an error code into a symbolic name for that error code. |
| 16846 | +*/ |
| 16847 | +static const char *vfstrace_errcode_name(int rc ){ |
| 16848 | + const char *zVal = 0; |
| 16849 | + switch( rc ){ |
| 16850 | + case SQLITE_OK: zVal = "SQLITE_OK"; break; |
| 16851 | + case SQLITE_INTERNAL: zVal = "SQLITE_INTERNAL"; break; |
| 16852 | + case SQLITE_ERROR: zVal = "SQLITE_ERROR"; break; |
| 16853 | + case SQLITE_PERM: zVal = "SQLITE_PERM"; break; |
| 16854 | + case SQLITE_ABORT: zVal = "SQLITE_ABORT"; break; |
| 16855 | + case SQLITE_BUSY: zVal = "SQLITE_BUSY"; break; |
| 16856 | + case SQLITE_LOCKED: zVal = "SQLITE_LOCKED"; break; |
| 16857 | + case SQLITE_NOMEM: zVal = "SQLITE_NOMEM"; break; |
| 16858 | + case SQLITE_READONLY: zVal = "SQLITE_READONLY"; break; |
| 16859 | + case SQLITE_INTERRUPT: zVal = "SQLITE_INTERRUPT"; break; |
| 16860 | + case SQLITE_IOERR: zVal = "SQLITE_IOERR"; break; |
| 16861 | + case SQLITE_CORRUPT: zVal = "SQLITE_CORRUPT"; break; |
| 16862 | + case SQLITE_NOTFOUND: zVal = "SQLITE_NOTFOUND"; break; |
| 16863 | + case SQLITE_FULL: zVal = "SQLITE_FULL"; break; |
| 16864 | + case SQLITE_CANTOPEN: zVal = "SQLITE_CANTOPEN"; break; |
| 16865 | + case SQLITE_PROTOCOL: zVal = "SQLITE_PROTOCOL"; break; |
| 16866 | + case SQLITE_EMPTY: zVal = "SQLITE_EMPTY"; break; |
| 16867 | + case SQLITE_SCHEMA: zVal = "SQLITE_SCHEMA"; break; |
| 16868 | + case SQLITE_TOOBIG: zVal = "SQLITE_TOOBIG"; break; |
| 16869 | + case SQLITE_CONSTRAINT: zVal = "SQLITE_CONSTRAINT"; break; |
| 16870 | + case SQLITE_MISMATCH: zVal = "SQLITE_MISMATCH"; break; |
| 16871 | + case SQLITE_MISUSE: zVal = "SQLITE_MISUSE"; break; |
| 16872 | + case SQLITE_NOLFS: zVal = "SQLITE_NOLFS"; break; |
| 16873 | + case SQLITE_IOERR_READ: zVal = "SQLITE_IOERR_READ"; break; |
| 16874 | + case SQLITE_IOERR_SHORT_READ: zVal = "SQLITE_IOERR_SHORT_READ"; break; |
| 16875 | + case SQLITE_IOERR_WRITE: zVal = "SQLITE_IOERR_WRITE"; break; |
| 16876 | + case SQLITE_IOERR_FSYNC: zVal = "SQLITE_IOERR_FSYNC"; break; |
| 16877 | + case SQLITE_IOERR_DIR_FSYNC: zVal = "SQLITE_IOERR_DIR_FSYNC"; break; |
| 16878 | + case SQLITE_IOERR_TRUNCATE: zVal = "SQLITE_IOERR_TRUNCATE"; break; |
| 16879 | + case SQLITE_IOERR_FSTAT: zVal = "SQLITE_IOERR_FSTAT"; break; |
| 16880 | + case SQLITE_IOERR_UNLOCK: zVal = "SQLITE_IOERR_UNLOCK"; break; |
| 16881 | + case SQLITE_IOERR_RDLOCK: zVal = "SQLITE_IOERR_RDLOCK"; break; |
| 16882 | + case SQLITE_IOERR_DELETE: zVal = "SQLITE_IOERR_DELETE"; break; |
| 16883 | + case SQLITE_IOERR_BLOCKED: zVal = "SQLITE_IOERR_BLOCKED"; break; |
| 16884 | + case SQLITE_IOERR_NOMEM: zVal = "SQLITE_IOERR_NOMEM"; break; |
| 16885 | + case SQLITE_IOERR_ACCESS: zVal = "SQLITE_IOERR_ACCESS"; break; |
| 16886 | + case SQLITE_IOERR_CHECKRESERVEDLOCK: |
| 16887 | + zVal = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; |
| 16888 | + case SQLITE_IOERR_LOCK: zVal = "SQLITE_IOERR_LOCK"; break; |
| 16889 | + case SQLITE_IOERR_CLOSE: zVal = "SQLITE_IOERR_CLOSE"; break; |
| 16890 | + case SQLITE_IOERR_DIR_CLOSE: zVal = "SQLITE_IOERR_DIR_CLOSE"; break; |
| 16891 | + case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break; |
| 16892 | + case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break; |
| 16893 | + case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break; |
| 16894 | + case SQLITE_IOERR_SHMMAP: zVal = "SQLITE_IOERR_SHMMAP"; break; |
| 16895 | + case SQLITE_IOERR_SEEK: zVal = "SQLITE_IOERR_SEEK"; break; |
| 16896 | + case SQLITE_IOERR_GETTEMPPATH: zVal = "SQLITE_IOERR_GETTEMPPATH"; break; |
| 16897 | + case SQLITE_IOERR_CONVPATH: zVal = "SQLITE_IOERR_CONVPATH"; break; |
| 16898 | + case SQLITE_READONLY_DBMOVED: zVal = "SQLITE_READONLY_DBMOVED"; break; |
| 16899 | + case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break; |
| 16900 | + case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break; |
| 16901 | + case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break; |
| 16902 | + } |
| 16903 | + return zVal; |
| 16904 | +} |
| 16905 | + |
| 16906 | +/* |
| 16907 | +** Convert value rc into a string and print it using zFormat. zFormat |
| 16908 | +** should have exactly one %s |
| 16909 | +*/ |
| 16910 | +static void vfstrace_print_errcode( |
| 16911 | + vfstrace_info *pInfo, |
| 16912 | + const char *zFormat, |
| 16913 | + int rc |
| 16914 | +){ |
| 16915 | + const char *zVal; |
| 16916 | + char zBuf[50]; |
| 16917 | + zVal = vfstrace_errcode_name(rc); |
| 16918 | + if( zVal==0 ){ |
| 16919 | + zVal = vfstrace_errcode_name(rc&0xff); |
| 16920 | + if( zVal ){ |
| 16921 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "%s | 0x%x", zVal, rc&0xffff00); |
| 16922 | + }else{ |
| 16923 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d (0x%x)", rc, rc); |
| 16924 | + } |
| 16925 | + zVal = zBuf; |
| 16926 | + } |
| 16927 | + vfstrace_printf(pInfo, zFormat, zVal); |
| 16928 | +} |
| 16929 | + |
| 16930 | +/* |
| 16931 | +** Append to a buffer. |
| 16932 | +*/ |
| 16933 | +static void strappend(char *z, int *pI, const char *zAppend){ |
| 16934 | + int i = *pI; |
| 16935 | + while( zAppend[0] ){ z[i++] = *(zAppend++); } |
| 16936 | + z[i] = 0; |
| 16937 | + *pI = i; |
| 16938 | +} |
| 16939 | + |
| 16940 | +/* |
| 16941 | +** Close an vfstrace-file. |
| 16942 | +*/ |
| 16943 | +static int vfstraceClose(sqlite3_file *pFile){ |
| 16944 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 16945 | + vfstrace_info *pInfo = p->pInfo; |
| 16946 | + int rc; |
| 16947 | + vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName); |
| 16948 | + rc = p->pReal->pMethods->xClose(p->pReal); |
| 16949 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 16950 | + if( rc==SQLITE_OK ){ |
| 16951 | + sqlite3_free((void*)p->base.pMethods); |
| 16952 | + p->base.pMethods = 0; |
| 16953 | + } |
| 16954 | + return rc; |
| 16955 | +} |
| 16956 | + |
| 16957 | +/* |
| 16958 | +** Read data from an vfstrace-file. |
| 16959 | +*/ |
| 16960 | +static int vfstraceRead( |
| 16961 | + sqlite3_file *pFile, |
| 16962 | + void *zBuf, |
| 16963 | + int iAmt, |
| 16964 | + sqlite_int64 iOfst |
| 16965 | +){ |
| 16966 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 16967 | + vfstrace_info *pInfo = p->pInfo; |
| 16968 | + int rc; |
| 16969 | + vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)", |
| 16970 | + pInfo->zVfsName, p->zFName, iAmt, iOfst); |
| 16971 | + rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); |
| 16972 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 16973 | + return rc; |
| 16974 | +} |
| 16975 | + |
| 16976 | +/* |
| 16977 | +** Write data to an vfstrace-file. |
| 16978 | +*/ |
| 16979 | +static int vfstraceWrite( |
| 16980 | + sqlite3_file *pFile, |
| 16981 | + const void *zBuf, |
| 16982 | + int iAmt, |
| 16983 | + sqlite_int64 iOfst |
| 16984 | +){ |
| 16985 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 16986 | + vfstrace_info *pInfo = p->pInfo; |
| 16987 | + int rc; |
| 16988 | + vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)", |
| 16989 | + pInfo->zVfsName, p->zFName, iAmt, iOfst); |
| 16990 | + rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); |
| 16991 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 16992 | + return rc; |
| 16993 | +} |
| 16994 | + |
| 16995 | +/* |
| 16996 | +** Truncate an vfstrace-file. |
| 16997 | +*/ |
| 16998 | +static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){ |
| 16999 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17000 | + vfstrace_info *pInfo = p->pInfo; |
| 17001 | + int rc; |
| 17002 | + vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName, |
| 17003 | + size); |
| 17004 | + rc = p->pReal->pMethods->xTruncate(p->pReal, size); |
| 17005 | + vfstrace_printf(pInfo, " -> %d\n", rc); |
| 17006 | + return rc; |
| 17007 | +} |
| 17008 | + |
| 17009 | +/* |
| 17010 | +** Sync an vfstrace-file. |
| 17011 | +*/ |
| 17012 | +static int vfstraceSync(sqlite3_file *pFile, int flags){ |
| 17013 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17014 | + vfstrace_info *pInfo = p->pInfo; |
| 17015 | + int rc; |
| 17016 | + int i; |
| 17017 | + char zBuf[100]; |
| 17018 | + memcpy(zBuf, "|0", 3); |
| 17019 | + i = 0; |
| 17020 | + if( flags & SQLITE_SYNC_FULL ) strappend(zBuf, &i, "|FULL"); |
| 17021 | + else if( flags & SQLITE_SYNC_NORMAL ) strappend(zBuf, &i, "|NORMAL"); |
| 17022 | + if( flags & SQLITE_SYNC_DATAONLY ) strappend(zBuf, &i, "|DATAONLY"); |
| 17023 | + if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){ |
| 17024 | + sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags); |
| 17025 | + } |
| 17026 | + vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName, |
| 17027 | + &zBuf[1]); |
| 17028 | + rc = p->pReal->pMethods->xSync(p->pReal, flags); |
| 17029 | + vfstrace_printf(pInfo, " -> %d\n", rc); |
| 17030 | + return rc; |
| 17031 | +} |
| 17032 | + |
| 17033 | +/* |
| 17034 | +** Return the current file-size of an vfstrace-file. |
| 17035 | +*/ |
| 17036 | +static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ |
| 17037 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17038 | + vfstrace_info *pInfo = p->pInfo; |
| 17039 | + int rc; |
| 17040 | + vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName); |
| 17041 | + rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); |
| 17042 | + vfstrace_print_errcode(pInfo, " -> %s,", rc); |
| 17043 | + vfstrace_printf(pInfo, " size=%lld\n", *pSize); |
| 17044 | + return rc; |
| 17045 | +} |
| 17046 | + |
| 17047 | +/* |
| 17048 | +** Return the name of a lock. |
| 17049 | +*/ |
| 17050 | +static const char *lockName(int eLock){ |
| 17051 | + const char *azLockNames[] = { |
| 17052 | + "NONE", "SHARED", "RESERVED", "PENDING", "EXCLUSIVE" |
| 17053 | + }; |
| 17054 | + if( eLock<0 || eLock>=sizeof(azLockNames)/sizeof(azLockNames[0]) ){ |
| 17055 | + return "???"; |
| 17056 | + }else{ |
| 17057 | + return azLockNames[eLock]; |
| 17058 | + } |
| 17059 | +} |
| 17060 | + |
| 17061 | +/* |
| 17062 | +** Lock an vfstrace-file. |
| 17063 | +*/ |
| 17064 | +static int vfstraceLock(sqlite3_file *pFile, int eLock){ |
| 17065 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17066 | + vfstrace_info *pInfo = p->pInfo; |
| 17067 | + int rc; |
| 17068 | + vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName, |
| 17069 | + lockName(eLock)); |
| 17070 | + rc = p->pReal->pMethods->xLock(p->pReal, eLock); |
| 17071 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 17072 | + return rc; |
| 17073 | +} |
| 17074 | + |
| 17075 | +/* |
| 17076 | +** Unlock an vfstrace-file. |
| 17077 | +*/ |
| 17078 | +static int vfstraceUnlock(sqlite3_file *pFile, int eLock){ |
| 17079 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17080 | + vfstrace_info *pInfo = p->pInfo; |
| 17081 | + int rc; |
| 17082 | + vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName, |
| 17083 | + lockName(eLock)); |
| 17084 | + rc = p->pReal->pMethods->xUnlock(p->pReal, eLock); |
| 17085 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 17086 | + return rc; |
| 17087 | +} |
| 17088 | + |
| 17089 | +/* |
| 17090 | +** Check if another file-handle holds a RESERVED lock on an vfstrace-file. |
| 17091 | +*/ |
| 17092 | +static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){ |
| 17093 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17094 | + vfstrace_info *pInfo = p->pInfo; |
| 17095 | + int rc; |
| 17096 | + vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)", |
| 17097 | + pInfo->zVfsName, p->zFName); |
| 17098 | + rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); |
| 17099 | + vfstrace_print_errcode(pInfo, " -> %s", rc); |
| 17100 | + vfstrace_printf(pInfo, ", out=%d\n", *pResOut); |
| 17101 | + return rc; |
| 17102 | +} |
| 17103 | + |
| 17104 | +/* |
| 17105 | +** File control method. For custom operations on an vfstrace-file. |
| 17106 | +*/ |
| 17107 | +static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){ |
| 17108 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17109 | + vfstrace_info *pInfo = p->pInfo; |
| 17110 | + int rc; |
| 17111 | + char zBuf[100]; |
| 17112 | + char zBuf2[100]; |
| 17113 | + char *zOp; |
| 17114 | + char *zRVal = 0; |
| 17115 | + switch( op ){ |
| 17116 | + case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break; |
| 17117 | + case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break; |
| 17118 | + case SQLITE_SET_LOCKPROXYFILE: zOp = "SET_LOCKPROXYFILE"; break; |
| 17119 | + case SQLITE_LAST_ERRNO: zOp = "LAST_ERRNO"; break; |
| 17120 | + case SQLITE_FCNTL_SIZE_HINT: { |
| 17121 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "SIZE_HINT,%lld", |
| 17122 | + *(sqlite3_int64*)pArg); |
| 17123 | + zOp = zBuf; |
| 17124 | + break; |
| 17125 | + } |
| 17126 | + case SQLITE_FCNTL_CHUNK_SIZE: { |
| 17127 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg); |
| 17128 | + zOp = zBuf; |
| 17129 | + break; |
| 17130 | + } |
| 17131 | + case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break; |
| 17132 | + case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break; |
| 17133 | + case SQLITE_FCNTL_PERSIST_WAL: { |
| 17134 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "PERSIST_WAL,%d", *(int*)pArg); |
| 17135 | + zOp = zBuf; |
| 17136 | + break; |
| 17137 | + } |
| 17138 | + case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break; |
| 17139 | + case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break; |
| 17140 | + case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break; |
| 17141 | + case SQLITE_FCNTL_PRAGMA: { |
| 17142 | + const char *const* a = (const char*const*)pArg; |
| 17143 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]); |
| 17144 | + zOp = zBuf; |
| 17145 | + break; |
| 17146 | + } |
| 17147 | + case SQLITE_FCNTL_BUSYHANDLER: zOp = "BUSYHANDLER"; break; |
| 17148 | + case SQLITE_FCNTL_TEMPFILENAME: zOp = "TEMPFILENAME"; break; |
| 17149 | + case SQLITE_FCNTL_MMAP_SIZE: { |
| 17150 | + sqlite3_int64 iMMap = *(sqlite3_int64*)pArg; |
| 17151 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "MMAP_SIZE,%lld",iMMap); |
| 17152 | + zOp = zBuf; |
| 17153 | + break; |
| 17154 | + } |
| 17155 | + case SQLITE_FCNTL_TRACE: zOp = "TRACE"; break; |
| 17156 | + case SQLITE_FCNTL_HAS_MOVED: zOp = "HAS_MOVED"; break; |
| 17157 | + case SQLITE_FCNTL_SYNC: zOp = "SYNC"; break; |
| 17158 | + case SQLITE_FCNTL_COMMIT_PHASETWO: zOp = "COMMIT_PHASETWO"; break; |
| 17159 | + case SQLITE_FCNTL_WIN32_SET_HANDLE: zOp = "WIN32_SET_HANDLE"; break; |
| 17160 | + case SQLITE_FCNTL_WAL_BLOCK: zOp = "WAL_BLOCK"; break; |
| 17161 | + case SQLITE_FCNTL_ZIPVFS: zOp = "ZIPVFS"; break; |
| 17162 | + case SQLITE_FCNTL_RBU: zOp = "RBU"; break; |
| 17163 | + case SQLITE_FCNTL_VFS_POINTER: zOp = "VFS_POINTER"; break; |
| 17164 | + case SQLITE_FCNTL_JOURNAL_POINTER: zOp = "JOURNAL_POINTER"; break; |
| 17165 | + case SQLITE_FCNTL_WIN32_GET_HANDLE: zOp = "WIN32_GET_HANDLE"; break; |
| 17166 | + case SQLITE_FCNTL_PDB: zOp = "PDB"; break; |
| 17167 | + case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: zOp = "BEGIN_ATOMIC_WRITE"; break; |
| 17168 | + case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: zOp = "COMMIT_ATOMIC_WRITE"; break; |
| 17169 | + case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: { |
| 17170 | + zOp = "ROLLBACK_ATOMIC_WRITE"; |
| 17171 | + break; |
| 17172 | + } |
| 17173 | + case SQLITE_FCNTL_LOCK_TIMEOUT: { |
| 17174 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "LOCK_TIMEOUT,%d", *(int*)pArg); |
| 17175 | + zOp = zBuf; |
| 17176 | + break; |
| 17177 | + } |
| 17178 | + case SQLITE_FCNTL_DATA_VERSION: zOp = "DATA_VERSION"; break; |
| 17179 | + case SQLITE_FCNTL_SIZE_LIMIT: zOp = "SIZE_LIMIT"; break; |
| 17180 | + case SQLITE_FCNTL_CKPT_DONE: zOp = "CKPT_DONE"; break; |
| 17181 | + case SQLITE_FCNTL_RESERVE_BYTES: zOp = "RESERVED_BYTES"; break; |
| 17182 | + case SQLITE_FCNTL_CKPT_START: zOp = "CKPT_START"; break; |
| 17183 | + case SQLITE_FCNTL_EXTERNAL_READER: zOp = "EXTERNAL_READER"; break; |
| 17184 | + case SQLITE_FCNTL_CKSM_FILE: zOp = "CKSM_FILE"; break; |
| 17185 | + case SQLITE_FCNTL_RESET_CACHE: zOp = "RESET_CACHE"; break; |
| 17186 | + case 0xca093fa0: zOp = "DB_UNCHANGED"; break; |
| 17187 | + default: { |
| 17188 | + sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op); |
| 17189 | + zOp = zBuf; |
| 17190 | + break; |
| 17191 | + } |
| 17192 | + } |
| 17193 | + vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)", |
| 17194 | + pInfo->zVfsName, p->zFName, zOp); |
| 17195 | + rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); |
| 17196 | + if( rc==SQLITE_OK ){ |
| 17197 | + switch( op ){ |
| 17198 | + case SQLITE_FCNTL_VFSNAME: { |
| 17199 | + *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z", |
| 17200 | + pInfo->zVfsName, *(char**)pArg); |
| 17201 | + zRVal = *(char**)pArg; |
| 17202 | + break; |
| 17203 | + } |
| 17204 | + case SQLITE_FCNTL_MMAP_SIZE: { |
| 17205 | + sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%lld", *(sqlite3_int64*)pArg); |
| 17206 | + zRVal = zBuf2; |
| 17207 | + break; |
| 17208 | + } |
| 17209 | + case SQLITE_FCNTL_HAS_MOVED: |
| 17210 | + case SQLITE_FCNTL_PERSIST_WAL: { |
| 17211 | + sqlite3_snprintf(sizeof(zBuf2), zBuf2, "%d", *(int*)pArg); |
| 17212 | + zRVal = zBuf2; |
| 17213 | + break; |
| 17214 | + } |
| 17215 | + case SQLITE_FCNTL_PRAGMA: |
| 17216 | + case SQLITE_FCNTL_TEMPFILENAME: { |
| 17217 | + zRVal = *(char**)pArg; |
| 17218 | + break; |
| 17219 | + } |
| 17220 | + } |
| 17221 | + } |
| 17222 | + if( zRVal ){ |
| 17223 | + vfstrace_print_errcode(pInfo, " -> %s", rc); |
| 17224 | + vfstrace_printf(pInfo, ", %s\n", zRVal); |
| 17225 | + }else{ |
| 17226 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 17227 | + } |
| 17228 | + return rc; |
| 17229 | +} |
| 17230 | + |
| 17231 | +/* |
| 17232 | +** Return the sector-size in bytes for an vfstrace-file. |
| 17233 | +*/ |
| 17234 | +static int vfstraceSectorSize(sqlite3_file *pFile){ |
| 17235 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17236 | + vfstrace_info *pInfo = p->pInfo; |
| 17237 | + int rc; |
| 17238 | + vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName); |
| 17239 | + rc = p->pReal->pMethods->xSectorSize(p->pReal); |
| 17240 | + vfstrace_printf(pInfo, " -> %d\n", rc); |
| 17241 | + return rc; |
| 17242 | +} |
| 17243 | + |
| 17244 | +/* |
| 17245 | +** Return the device characteristic flags supported by an vfstrace-file. |
| 17246 | +*/ |
| 17247 | +static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){ |
| 17248 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17249 | + vfstrace_info *pInfo = p->pInfo; |
| 17250 | + int rc; |
| 17251 | + vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)", |
| 17252 | + pInfo->zVfsName, p->zFName); |
| 17253 | + rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal); |
| 17254 | + vfstrace_printf(pInfo, " -> 0x%08x\n", rc); |
| 17255 | + return rc; |
| 17256 | +} |
| 17257 | + |
| 17258 | +/* |
| 17259 | +** Shared-memory operations. |
| 17260 | +*/ |
| 17261 | +static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ |
| 17262 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17263 | + vfstrace_info *pInfo = p->pInfo; |
| 17264 | + int rc; |
| 17265 | + char zLck[100]; |
| 17266 | + int i = 0; |
| 17267 | + memcpy(zLck, "|0", 3); |
| 17268 | + if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK"); |
| 17269 | + if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK"); |
| 17270 | + if( flags & SQLITE_SHM_SHARED ) strappend(zLck, &i, "|SHARED"); |
| 17271 | + if( flags & SQLITE_SHM_EXCLUSIVE ) strappend(zLck, &i, "|EXCLUSIVE"); |
| 17272 | + if( flags & ~(0xf) ){ |
| 17273 | + sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags); |
| 17274 | + } |
| 17275 | + vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)", |
| 17276 | + pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]); |
| 17277 | + rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); |
| 17278 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 17279 | + return rc; |
| 17280 | +} |
| 17281 | +static int vfstraceShmMap( |
| 17282 | + sqlite3_file *pFile, |
| 17283 | + int iRegion, |
| 17284 | + int szRegion, |
| 17285 | + int isWrite, |
| 17286 | + void volatile **pp |
| 17287 | +){ |
| 17288 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17289 | + vfstrace_info *pInfo = p->pInfo; |
| 17290 | + int rc; |
| 17291 | + vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)", |
| 17292 | + pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite); |
| 17293 | + rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); |
| 17294 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 17295 | + return rc; |
| 17296 | +} |
| 17297 | +static void vfstraceShmBarrier(sqlite3_file *pFile){ |
| 17298 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17299 | + vfstrace_info *pInfo = p->pInfo; |
| 17300 | + vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName); |
| 17301 | + p->pReal->pMethods->xShmBarrier(p->pReal); |
| 17302 | +} |
| 17303 | +static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){ |
| 17304 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17305 | + vfstrace_info *pInfo = p->pInfo; |
| 17306 | + int rc; |
| 17307 | + vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)", |
| 17308 | + pInfo->zVfsName, p->zFName, delFlag); |
| 17309 | + rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); |
| 17310 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 17311 | + return rc; |
| 17312 | +} |
| 17313 | + |
| 17314 | + |
| 17315 | + |
| 17316 | +/* |
| 17317 | +** Open an vfstrace file handle. |
| 17318 | +*/ |
| 17319 | +static int vfstraceOpen( |
| 17320 | + sqlite3_vfs *pVfs, |
| 17321 | + const char *zName, |
| 17322 | + sqlite3_file *pFile, |
| 17323 | + int flags, |
| 17324 | + int *pOutFlags |
| 17325 | +){ |
| 17326 | + int rc; |
| 17327 | + vfstrace_file *p = (vfstrace_file *)pFile; |
| 17328 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17329 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17330 | + p->pInfo = pInfo; |
| 17331 | + p->zFName = zName ? fileTail(zName) : "<temp>"; |
| 17332 | + p->pReal = (sqlite3_file *)&p[1]; |
| 17333 | + rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags); |
| 17334 | + vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)", |
| 17335 | + pInfo->zVfsName, p->zFName, flags); |
| 17336 | + if( p->pReal->pMethods ){ |
| 17337 | + sqlite3_io_methods *pNew = sqlite3_malloc( sizeof(*pNew) ); |
| 17338 | + const sqlite3_io_methods *pSub = p->pReal->pMethods; |
| 17339 | + memset(pNew, 0, sizeof(*pNew)); |
| 17340 | + pNew->iVersion = pSub->iVersion; |
| 17341 | + pNew->xClose = vfstraceClose; |
| 17342 | + pNew->xRead = vfstraceRead; |
| 17343 | + pNew->xWrite = vfstraceWrite; |
| 17344 | + pNew->xTruncate = vfstraceTruncate; |
| 17345 | + pNew->xSync = vfstraceSync; |
| 17346 | + pNew->xFileSize = vfstraceFileSize; |
| 17347 | + pNew->xLock = vfstraceLock; |
| 17348 | + pNew->xUnlock = vfstraceUnlock; |
| 17349 | + pNew->xCheckReservedLock = vfstraceCheckReservedLock; |
| 17350 | + pNew->xFileControl = vfstraceFileControl; |
| 17351 | + pNew->xSectorSize = vfstraceSectorSize; |
| 17352 | + pNew->xDeviceCharacteristics = vfstraceDeviceCharacteristics; |
| 17353 | + if( pNew->iVersion>=2 ){ |
| 17354 | + pNew->xShmMap = pSub->xShmMap ? vfstraceShmMap : 0; |
| 17355 | + pNew->xShmLock = pSub->xShmLock ? vfstraceShmLock : 0; |
| 17356 | + pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0; |
| 17357 | + pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0; |
| 17358 | + } |
| 17359 | + pFile->pMethods = pNew; |
| 17360 | + } |
| 17361 | + vfstrace_print_errcode(pInfo, " -> %s", rc); |
| 17362 | + if( pOutFlags ){ |
| 17363 | + vfstrace_printf(pInfo, ", outFlags=0x%x\n", *pOutFlags); |
| 17364 | + }else{ |
| 17365 | + vfstrace_printf(pInfo, "\n"); |
| 17366 | + } |
| 17367 | + return rc; |
| 17368 | +} |
| 17369 | + |
| 17370 | +/* |
| 17371 | +** Delete the file located at zPath. If the dirSync argument is true, |
| 17372 | +** ensure the file-system modifications are synced to disk before |
| 17373 | +** returning. |
| 17374 | +*/ |
| 17375 | +static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
| 17376 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17377 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17378 | + int rc; |
| 17379 | + vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)", |
| 17380 | + pInfo->zVfsName, zPath, dirSync); |
| 17381 | + rc = pRoot->xDelete(pRoot, zPath, dirSync); |
| 17382 | + vfstrace_print_errcode(pInfo, " -> %s\n", rc); |
| 17383 | + return rc; |
| 17384 | +} |
| 17385 | + |
| 17386 | +/* |
| 17387 | +** Test for access permissions. Return true if the requested permission |
| 17388 | +** is available, or false otherwise. |
| 17389 | +*/ |
| 17390 | +static int vfstraceAccess( |
| 17391 | + sqlite3_vfs *pVfs, |
| 17392 | + const char *zPath, |
| 17393 | + int flags, |
| 17394 | + int *pResOut |
| 17395 | +){ |
| 17396 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17397 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17398 | + int rc; |
| 17399 | + vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)", |
| 17400 | + pInfo->zVfsName, zPath, flags); |
| 17401 | + rc = pRoot->xAccess(pRoot, zPath, flags, pResOut); |
| 17402 | + vfstrace_print_errcode(pInfo, " -> %s", rc); |
| 17403 | + vfstrace_printf(pInfo, ", out=%d\n", *pResOut); |
| 17404 | + return rc; |
| 17405 | +} |
| 17406 | + |
| 17407 | +/* |
| 17408 | +** Populate buffer zOut with the full canonical pathname corresponding |
| 17409 | +** to the pathname in zPath. zOut is guaranteed to point to a buffer |
| 17410 | +** of at least (DEVSYM_MAX_PATHNAME+1) bytes. |
| 17411 | +*/ |
| 17412 | +static int vfstraceFullPathname( |
| 17413 | + sqlite3_vfs *pVfs, |
| 17414 | + const char *zPath, |
| 17415 | + int nOut, |
| 17416 | + char *zOut |
| 17417 | +){ |
| 17418 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17419 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17420 | + int rc; |
| 17421 | + vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")", |
| 17422 | + pInfo->zVfsName, zPath); |
| 17423 | + rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut); |
| 17424 | + vfstrace_print_errcode(pInfo, " -> %s", rc); |
| 17425 | + vfstrace_printf(pInfo, ", out=\"%.*s\"\n", nOut, zOut); |
| 17426 | + return rc; |
| 17427 | +} |
| 17428 | + |
| 17429 | +/* |
| 17430 | +** Open the dynamic library located at zPath and return a handle. |
| 17431 | +*/ |
| 17432 | +static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){ |
| 17433 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17434 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17435 | + vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath); |
| 17436 | + return pRoot->xDlOpen(pRoot, zPath); |
| 17437 | +} |
| 17438 | + |
| 17439 | +/* |
| 17440 | +** Populate the buffer zErrMsg (size nByte bytes) with a human readable |
| 17441 | +** utf-8 string describing the most recent error encountered associated |
| 17442 | +** with dynamic libraries. |
| 17443 | +*/ |
| 17444 | +static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ |
| 17445 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17446 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17447 | + vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte); |
| 17448 | + pRoot->xDlError(pRoot, nByte, zErrMsg); |
| 17449 | + vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg); |
| 17450 | +} |
| 17451 | + |
| 17452 | +/* |
| 17453 | +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. |
| 17454 | +*/ |
| 17455 | +static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){ |
| 17456 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17457 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17458 | + vfstrace_printf(pInfo, "%s.xDlSym(\"%s\")\n", pInfo->zVfsName, zSym); |
| 17459 | + return pRoot->xDlSym(pRoot, p, zSym); |
| 17460 | +} |
| 17461 | + |
| 17462 | +/* |
| 17463 | +** Close the dynamic library handle pHandle. |
| 17464 | +*/ |
| 17465 | +static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
| 17466 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17467 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17468 | + vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName); |
| 17469 | + pRoot->xDlClose(pRoot, pHandle); |
| 17470 | +} |
| 17471 | + |
| 17472 | +/* |
| 17473 | +** Populate the buffer pointed to by zBufOut with nByte bytes of |
| 17474 | +** random data. |
| 17475 | +*/ |
| 17476 | +static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ |
| 17477 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17478 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17479 | + vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte); |
| 17480 | + return pRoot->xRandomness(pRoot, nByte, zBufOut); |
| 17481 | +} |
| 17482 | + |
| 17483 | +/* |
| 17484 | +** Sleep for nMicro microseconds. Return the number of microseconds |
| 17485 | +** actually slept. |
| 17486 | +*/ |
| 17487 | +static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){ |
| 17488 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17489 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17490 | + return pRoot->xSleep(pRoot, nMicro); |
| 17491 | +} |
| 17492 | + |
| 17493 | +/* |
| 17494 | +** Return the current time as a Julian Day number in *pTimeOut. |
| 17495 | +*/ |
| 17496 | +static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ |
| 17497 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17498 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17499 | + return pRoot->xCurrentTime(pRoot, pTimeOut); |
| 17500 | +} |
| 17501 | +static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ |
| 17502 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17503 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17504 | + return pRoot->xCurrentTimeInt64(pRoot, pTimeOut); |
| 17505 | +} |
| 17506 | + |
| 17507 | +/* |
| 17508 | +** Return th3 most recent error code and message |
| 17509 | +*/ |
| 17510 | +static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){ |
| 17511 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17512 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17513 | + return pRoot->xGetLastError(pRoot, iErr, zErr); |
| 17514 | +} |
| 17515 | + |
| 17516 | +/* |
| 17517 | +** Override system calls. |
| 17518 | +*/ |
| 17519 | +static int vfstraceSetSystemCall( |
| 17520 | + sqlite3_vfs *pVfs, |
| 17521 | + const char *zName, |
| 17522 | + sqlite3_syscall_ptr pFunc |
| 17523 | +){ |
| 17524 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17525 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17526 | + return pRoot->xSetSystemCall(pRoot, zName, pFunc); |
| 17527 | +} |
| 17528 | +static sqlite3_syscall_ptr vfstraceGetSystemCall( |
| 17529 | + sqlite3_vfs *pVfs, |
| 17530 | + const char *zName |
| 17531 | +){ |
| 17532 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17533 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17534 | + return pRoot->xGetSystemCall(pRoot, zName); |
| 17535 | +} |
| 17536 | +static const char *vfstraceNextSystemCall(sqlite3_vfs *pVfs, const char *zName){ |
| 17537 | + vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData; |
| 17538 | + sqlite3_vfs *pRoot = pInfo->pRootVfs; |
| 17539 | + return pRoot->xNextSystemCall(pRoot, zName); |
| 17540 | +} |
| 17541 | + |
| 17542 | + |
| 17543 | +/* |
| 17544 | +** Clients invoke this routine to construct a new trace-vfs shim. |
| 17545 | +** |
| 17546 | +** Return SQLITE_OK on success. |
| 17547 | +** |
| 17548 | +** SQLITE_NOMEM is returned in the case of a memory allocation error. |
| 17549 | +** SQLITE_NOTFOUND is returned if zOldVfsName does not exist. |
| 17550 | +*/ |
| 17551 | +int vfstrace_register( |
| 17552 | + const char *zTraceName, /* Name of the newly constructed VFS */ |
| 17553 | + const char *zOldVfsName, /* Name of the underlying VFS */ |
| 17554 | + int (*xOut)(const char*,void*), /* Output routine. ex: fputs */ |
| 17555 | + void *pOutArg, /* 2nd argument to xOut. ex: stderr */ |
| 17556 | + int makeDefault /* True to make the new VFS the default */ |
| 17557 | +){ |
| 17558 | + sqlite3_vfs *pNew; |
| 17559 | + sqlite3_vfs *pRoot; |
| 17560 | + vfstrace_info *pInfo; |
| 17561 | + size_t nName; |
| 17562 | + size_t nByte; |
| 17563 | + |
| 17564 | + pRoot = sqlite3_vfs_find(zOldVfsName); |
| 17565 | + if( pRoot==0 ) return SQLITE_NOTFOUND; |
| 17566 | + nName = strlen(zTraceName); |
| 17567 | + nByte = sizeof(*pNew) + sizeof(*pInfo) + nName + 1; |
| 17568 | + pNew = sqlite3_malloc64( nByte ); |
| 17569 | + if( pNew==0 ) return SQLITE_NOMEM; |
| 17570 | + memset(pNew, 0, nByte); |
| 17571 | + pInfo = (vfstrace_info*)&pNew[1]; |
| 17572 | + pNew->iVersion = pRoot->iVersion; |
| 17573 | + pNew->szOsFile = pRoot->szOsFile + sizeof(vfstrace_file); |
| 17574 | + pNew->mxPathname = pRoot->mxPathname; |
| 17575 | + pNew->zName = (char*)&pInfo[1]; |
| 17576 | + memcpy((char*)&pInfo[1], zTraceName, nName+1); |
| 17577 | + pNew->pAppData = pInfo; |
| 17578 | + pNew->xOpen = vfstraceOpen; |
| 17579 | + pNew->xDelete = vfstraceDelete; |
| 17580 | + pNew->xAccess = vfstraceAccess; |
| 17581 | + pNew->xFullPathname = vfstraceFullPathname; |
| 17582 | + pNew->xDlOpen = pRoot->xDlOpen==0 ? 0 : vfstraceDlOpen; |
| 17583 | + pNew->xDlError = pRoot->xDlError==0 ? 0 : vfstraceDlError; |
| 17584 | + pNew->xDlSym = pRoot->xDlSym==0 ? 0 : vfstraceDlSym; |
| 17585 | + pNew->xDlClose = pRoot->xDlClose==0 ? 0 : vfstraceDlClose; |
| 17586 | + pNew->xRandomness = vfstraceRandomness; |
| 17587 | + pNew->xSleep = vfstraceSleep; |
| 17588 | + pNew->xCurrentTime = vfstraceCurrentTime; |
| 17589 | + pNew->xGetLastError = pRoot->xGetLastError==0 ? 0 : vfstraceGetLastError; |
| 17590 | + if( pNew->iVersion>=2 ){ |
| 17591 | + pNew->xCurrentTimeInt64 = pRoot->xCurrentTimeInt64==0 ? 0 : |
| 17592 | + vfstraceCurrentTimeInt64; |
| 17593 | + if( pNew->iVersion>=3 ){ |
| 17594 | + pNew->xSetSystemCall = pRoot->xSetSystemCall==0 ? 0 : |
| 17595 | + vfstraceSetSystemCall; |
| 17596 | + pNew->xGetSystemCall = pRoot->xGetSystemCall==0 ? 0 : |
| 17597 | + vfstraceGetSystemCall; |
| 17598 | + pNew->xNextSystemCall = pRoot->xNextSystemCall==0 ? 0 : |
| 17599 | + vfstraceNextSystemCall; |
| 17600 | + } |
| 17601 | + } |
| 17602 | + pInfo->pRootVfs = pRoot; |
| 17603 | + pInfo->xOut = xOut; |
| 17604 | + pInfo->pOutArg = pOutArg; |
| 17605 | + pInfo->zVfsName = pNew->zName; |
| 17606 | + pInfo->pTraceVfs = pNew; |
| 17607 | + vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n", |
| 17608 | + pInfo->zVfsName, pRoot->zName); |
| 17609 | + return sqlite3_vfs_register(pNew, makeDefault); |
| 17610 | +} |
| 17611 | + |
| 17612 | +/* |
| 17613 | +** Look for the named VFS. If it is a TRACEVFS, then unregister it |
| 17614 | +** and delete it. |
| 17615 | +*/ |
| 17616 | +void vfstrace_unregister(const char *zTraceName){ |
| 17617 | + sqlite3_vfs *pVfs = sqlite3_vfs_find(zTraceName); |
| 17618 | + if( pVfs==0 ) return; |
| 17619 | + if( pVfs->xOpen!=vfstraceOpen ) return; |
| 17620 | + sqlite3_vfs_unregister(pVfs); |
| 17621 | + sqlite3_free(pVfs); |
| 17622 | +} |
| 17623 | + |
| 17624 | +/************************* End ../ext/misc/vfstrace.c ********************/ |
| 16216 | 17625 | |
| 16217 | 17626 | #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) |
| 16218 | 17627 | #define SQLITE_SHELL_HAVE_RECOVER 1 |
| 16219 | 17628 | #else |
| 16220 | 17629 | #define SQLITE_SHELL_HAVE_RECOVER 0 |
| | @@ -24511,10 +25920,11 @@ |
| 24511 | 25920 | } |
| 24512 | 25921 | |
| 24513 | 25922 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 24514 | 25923 | sqlite3_enable_load_extension(p->db, 1); |
| 24515 | 25924 | #endif |
| 25925 | + sqlite3_sha_init(p->db, 0, 0); |
| 24516 | 25926 | sqlite3_shathree_init(p->db, 0, 0); |
| 24517 | 25927 | sqlite3_uint_init(p->db, 0, 0); |
| 24518 | 25928 | sqlite3_stmtrand_init(p->db, 0, 0); |
| 24519 | 25929 | sqlite3_decimal_init(p->db, 0, 0); |
| 24520 | 25930 | sqlite3_percentile_init(p->db, 0, 0); |
| | @@ -31374,13 +32784,11 @@ |
| 31374 | 32784 | " -table set output mode to 'table'\n" |
| 31375 | 32785 | " -tabs set output mode to 'tabs'\n" |
| 31376 | 32786 | " -unsafe-testing allow unsafe commands and modes for testing\n" |
| 31377 | 32787 | " -version show SQLite version\n" |
| 31378 | 32788 | " -vfs NAME use NAME as the default VFS\n" |
| 31379 | | -#ifdef SQLITE_ENABLE_VFSTRACE |
| 31380 | 32789 | " -vfstrace enable tracing of all VFS calls\n" |
| 31381 | | -#endif |
| 31382 | 32790 | #ifdef SQLITE_HAVE_ZLIB |
| 31383 | 32791 | " -zip open the file as a ZIP Archive\n" |
| 31384 | 32792 | #endif |
| 31385 | 32793 | ; |
| 31386 | 32794 | static void usage(int showDetail){ |
| | @@ -31502,10 +32910,11 @@ |
| 31502 | 32910 | int rc = 0; |
| 31503 | 32911 | int warnInmemoryDb = 0; |
| 31504 | 32912 | int readStdin = 1; |
| 31505 | 32913 | int nCmd = 0; |
| 31506 | 32914 | int nOptsEnd = argc; |
| 32915 | + int bEnableVfstrace = 0; |
| 31507 | 32916 | char **azCmd = 0; |
| 31508 | 32917 | const char *zVfs = 0; /* Value of -vfs command-line option */ |
| 31509 | 32918 | #if !SQLITE_SHELL_IS_UTF8 |
| 31510 | 32919 | char **argvToFree = 0; |
| 31511 | 32920 | int argcToFree = 0; |
| | @@ -31696,21 +33105,13 @@ |
| 31696 | 33105 | switch( n ){ |
| 31697 | 33106 | case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break; |
| 31698 | 33107 | case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break; |
| 31699 | 33108 | default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break; |
| 31700 | 33109 | } |
| 31701 | | -#ifdef SQLITE_ENABLE_VFSTRACE |
| 31702 | 33110 | }else if( cli_strcmp(z,"-vfstrace")==0 ){ |
| 31703 | | - extern int vfstrace_register( |
| 31704 | | - const char *zTraceName, |
| 31705 | | - const char *zOldVfsName, |
| 31706 | | - int (*xOut)(const char*,void*), |
| 31707 | | - void *pOutArg, |
| 31708 | | - int makeDefault |
| 31709 | | - ); |
| 31710 | 33111 | vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); |
| 31711 | | -#endif |
| 33112 | + bEnableVfstrace = 1; |
| 31712 | 33113 | #ifdef SQLITE_ENABLE_MULTIPLEX |
| 31713 | 33114 | }else if( cli_strcmp(z,"-multiplex")==0 ){ |
| 31714 | 33115 | extern int sqlite3_multiplex_initialize(const char*,int); |
| 31715 | 33116 | sqlite3_multiplex_initialize(0, 1); |
| 31716 | 33117 | #endif |
| | @@ -31762,11 +33163,11 @@ |
| 31762 | 33163 | }else if( cli_strcmp(z,"-safe")==0 ){ |
| 31763 | 33164 | /* no-op - catch this on the second pass */ |
| 31764 | 33165 | } |
| 31765 | 33166 | } |
| 31766 | 33167 | #ifndef SQLITE_SHELL_FIDDLE |
| 31767 | | - verify_uninitialized(); |
| 33168 | + if( !bEnableVfstrace ) verify_uninitialized(); |
| 31768 | 33169 | #endif |
| 31769 | 33170 | |
| 31770 | 33171 | |
| 31771 | 33172 | #ifdef SQLITE_SHELL_INIT_PROC |
| 31772 | 33173 | { |
| | @@ -31951,14 +33352,12 @@ |
| 31951 | 33352 | }else if( cli_strcmp(z,"-sorterref")==0 ){ |
| 31952 | 33353 | i++; |
| 31953 | 33354 | #endif |
| 31954 | 33355 | }else if( cli_strcmp(z,"-vfs")==0 ){ |
| 31955 | 33356 | i++; |
| 31956 | | -#ifdef SQLITE_ENABLE_VFSTRACE |
| 31957 | 33357 | }else if( cli_strcmp(z,"-vfstrace")==0 ){ |
| 31958 | 33358 | i++; |
| 31959 | | -#endif |
| 31960 | 33359 | #ifdef SQLITE_ENABLE_MULTIPLEX |
| 31961 | 33360 | }else if( cli_strcmp(z,"-multiplex")==0 ){ |
| 31962 | 33361 | i++; |
| 31963 | 33362 | #endif |
| 31964 | 33363 | }else if( cli_strcmp(z,"-help")==0 ){ |
| | @@ -32122,10 +33521,13 @@ |
| 32122 | 33521 | free(data.colWidth); |
| 32123 | 33522 | free(data.zNonce); |
| 32124 | 33523 | /* Clear the global data structure so that valgrind will detect memory |
| 32125 | 33524 | ** leaks */ |
| 32126 | 33525 | memset(&data, 0, sizeof(data)); |
| 33526 | + if( bEnableVfstrace ){ |
| 33527 | + vfstrace_unregister("trace"); |
| 33528 | + } |
| 32127 | 33529 | #ifdef SQLITE_DEBUG |
| 32128 | 33530 | if( sqlite3_memory_used()>mem_main_enter ){ |
| 32129 | 33531 | eputf("Memory leaked: %u bytes\n", |
| 32130 | 33532 | (unsigned int)(sqlite3_memory_used()-mem_main_enter)); |
| 32131 | 33533 | } |
| 32132 | 33534 | |