From 1fa6d9f96f8cda45b2a3123241cd7e4971914830 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 6 Jan 2018 21:46:01 +0000 Subject: [PATCH] The shell detects and opens ZIP archives using the zipfile extension. FossilOrigin-Name: 05c99eb8cefbb3366b6d4ae91e10aa0c82bdf5ea361f4b3375413783af9167ac --- manifest | 12 ++++---- manifest.uuid | 2 +- src/shell.c.in | 83 +++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 59f92e796c..83bebcd068 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sshell,\sinclude\sthe\s".archive"\scommand\sonly\sif\scompiling\swith\nSQLITE_HAVE_ZLIB.\s\sAdd\s".archive"\sto\sthe\s".help"\soutput. -D 2018-01-06T19:19:50.442 +C The\sshell\sdetects\sand\sopens\sZIP\sarchives\susing\sthe\szipfile\sextension. +D 2018-01-06T21:46:01.434 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 9536f61ce33172d4868707ecc10844a0abef9e2e775ad2434245a60406fd7e38 @@ -484,7 +484,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in 9f2ab2d0b4b07310950ec84492c067f9c65a2c934b2704f07bf3f7abd81b1326 +F src/shell.c.in c2231d96fc059e2a6c86d67571db0dc7e029de25553a42c3334a6ef4c8e92484 F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 @@ -1697,7 +1697,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 252ee55a7fc0b068b707af27bd912e684c28320996e78f0675217046b8c2fb49 -R 1106ed2dd57a38999d04b0134db88743 +P 366469f5603367fabcadfc9ffe8cd1e23c649fea49a560178ca0858a16a7e4d1 +R 0f23134ec1d9b30706dc56d4edcd4f2b U drh -Z 0971e8c5cac3e7845d10877eae148e13 +Z bf2fee513f6949a58534392bd37a9abf diff --git a/manifest.uuid b/manifest.uuid index 289c74b7d1..95d424063b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -366469f5603367fabcadfc9ffe8cd1e23c649fea49a560178ca0858a16a7e4d1 \ No newline at end of file +05c99eb8cefbb3366b6d4ae91e10aa0c82bdf5ea361f4b3375413783af9167ac \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index bff3684321..71f9f19cb2 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -63,6 +63,7 @@ #include "sqlite3.h" typedef sqlite3_int64 i64; typedef sqlite3_uint64 u64; +typedef unsigned char u8; #if SQLITE_USER_AUTHENTICATION # include "sqlite3userauth.h" #endif @@ -938,10 +939,11 @@ struct ExpertInfo { typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ - int autoExplain; /* Automatically turn on .explain mode */ - int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ - int statsOn; /* True to display memory stats before each finalize */ - int scanstatsOn; /* True to display scan stats before each finalize */ + u8 autoExplain; /* Automatically turn on .explain mode */ + u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ + u8 statsOn; /* True to display memory stats before each finalize */ + u8 scanstatsOn; /* True to display scan stats before each finalize */ + u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ @@ -978,6 +980,7 @@ struct ShellState { ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */ }; + /* Allowed values for ShellState.autoEQP */ #define AUTOEQP_off 0 @@ -985,6 +988,13 @@ struct ShellState { #define AUTOEQP_trigger 2 #define AUTOEQP_full 3 +/* Allowed values for ShellState.openMode +*/ +#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ +#define SHELL_OPEN_NORMAL 1 /* Normal database file */ +#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ +#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ + /* ** These are the allowed shellFlgs values */ @@ -3101,6 +3111,32 @@ static int session_filter(void *pCtx, const char *zTab){ } #endif +/* +** Try to deduce the type of file for zName based on its content. Return +** one of the SHELL_OPEN_* constants. +*/ +static int deduceDatabaseType(const char *zName){ + FILE *f = fopen(zName, "rb"); + size_t n; + int rc = SHELL_OPEN_UNSPEC; + char zBuf[100]; + if( f==0 ) return SHELL_OPEN_NORMAL; + fseek(f, -25, SEEK_END); + n = fread(zBuf, 25, 1, f); + if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){ + rc = SHELL_OPEN_APPENDVFS; + }else{ + fseek(f, -22, SEEK_END); + n = fread(zBuf, 22, 1, f); + if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05 + && zBuf[3]==0x06 ){ + rc = SHELL_OPEN_ZIPFILE; + } + } + fclose(f); + return rc; +} + /* ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. @@ -3108,7 +3144,25 @@ static int session_filter(void *pCtx, const char *zTab){ static void open_db(ShellState *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); - sqlite3_open(p->zDbFilename, &p->db); + if( p->openMode==SHELL_OPEN_UNSPEC && access(p->zDbFilename,0)==0 ){ + p->openMode = deduceDatabaseType(p->zDbFilename); + } + switch( p->openMode ){ + case SHELL_OPEN_APPENDVFS: { + sqlite3_open_v2(p->zDbFilename, &p->db, + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs"); + break; + } + case SHELL_OPEN_ZIPFILE: { + sqlite3_open(":memory:", &p->db); + break; + } + case SHELL_OPEN_UNSPEC: + case SHELL_OPEN_NORMAL: { + sqlite3_open(p->zDbFilename, &p->db); + break; + } + } globalDb = p->db; if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", @@ -3130,6 +3184,12 @@ static void open_db(ShellState *p, int keepAlive){ shellAddSchemaName, 0, 0); sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, shellModuleSchema, 0, 0); + if( p->openMode==SHELL_OPEN_ZIPFILE ){ + char *zSql = sqlite3_mprintf( + "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename); + sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + } } } @@ -6012,11 +6072,18 @@ static int do_meta_command(char *zLine, ShellState *p){ p->zDbFilename = 0; sqlite3_free(p->zFreeOnClose); p->zFreeOnClose = 0; + p->openMode = SHELL_OPEN_UNSPEC; /* Check for command-line arguments */ for(iName=1; iNameopenMode = SHELL_OPEN_ZIPFILE; +#endif + }else if( optionMatch(z, "append") ){ + p->openMode = SHELL_OPEN_APPENDVFS; }else if( z[0]=='-' ){ utf8_printf(stderr, "unknown option: %s\n", z); rc = 1; @@ -7937,6 +8004,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ }else if( strcmp(z,"-csv")==0 ){ data.mode = MODE_Csv; memcpy(data.colSeparator,",",2); +#ifdef SQLITE_HAVE_ZIP + }else if( strcmp(z,"-zip")==0 ){ + data.openMode = SHELL_OPEN_ZIPFILE; +#endif + }else if( strcmp(z,"-append")==0 ){ + data.openMode = SHELL_OPEN_APPENDVFS; }else if( strcmp(z,"-ascii")==0 ){ data.mode = MODE_Ascii; sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, -- 2.47.2