︙ | | |
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
|
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
|
-
+
+
-
+
|
/*
** Structure representing a single ".ar" command.
*/
typedef struct ArCommand ArCommand;
struct ArCommand {
u8 eCmd; /* An AR_CMD_* value */
u8 bVerbose; /* True if --verbose */
u8 bZip; /* True if --zip */
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
int nArg; /* Number of command arguments */
const char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
const char *zFile; /* --file argument, or NULL */
const char *zDir; /* --directory argument, or NULL */
char **azArg; /* Array of command arguments */
ShellState *p; /* Shell state */
sqlite3 *db; /* Database containing the archive */
};
|
︙ | | |
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
|
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
|
-
+
|
" -x, --extract Extract files from archive\n"
"\n"
"And zero or more optional options:\n"
" -v, --verbose Print each filename as it is processed\n"
" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
" -C DIR, --directory DIR Change to directory DIR to read/extract files\n"
" -n, --dryrun Show the SQL that would have occurred\n"
" -z, --zip Operate on a ZIP archive instead of an SQLAR\n"
" -a, --append Append the SQLAR to an existing file\n"
"\n"
"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
"\n"
);
return SQLITE_ERROR;
}
|
︙ | | |
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
|
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
|
-
+
|
/*
** Other (non-command) switches.
*/
#define AR_SWITCH_VERBOSE 6
#define AR_SWITCH_FILE 7
#define AR_SWITCH_DIRECTORY 8
#define AR_SWITCH_ZIP 9
#define AR_SWITCH_APPEND 9
#define AR_SWITCH_DRYRUN 10
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
case AR_CMD_CREATE:
case AR_CMD_EXTRACT:
case AR_CMD_LIST:
|
︙ | | |
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
|
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
|
-
-
+
+
|
case AR_SWITCH_DRYRUN:
pAr->bDryRun = 1;
break;
case AR_SWITCH_VERBOSE:
pAr->bVerbose = 1;
break;
case AR_SWITCH_ZIP:
pAr->bZip = 1;
case AR_SWITCH_APPEND:
pAr->bAppend = 1;
break;
case AR_SWITCH_FILE:
pAr->zFile = zArg;
break;
case AR_SWITCH_DIRECTORY:
pAr->zDir = zArg;
|
︙ | | |
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
|
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
|
-
+
|
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
{ "list", 't', AR_CMD_LIST, 0 },
{ "update", 'u', AR_CMD_UPDATE, 0 },
{ "help", 'h', AR_CMD_HELP, 0 },
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
{ "file", 'f', AR_SWITCH_FILE, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "zip", 'z', AR_SWITCH_ZIP, 0 },
{ "append", 'a', AR_SWITCH_APPEND, 0 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
return arUsage(stderr);
|
︙ | | |
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
|
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
|
-
-
-
-
-
|
int i, j;
sqlite3_stmt *pTest = 0;
shellPreparePrintf(pAr->db, &rc, &pTest,
"SELECT name FROM %s WHERE name=$name",
pAr->zSrcTable
);
if( rc==SQLITE_OK
&& (j = sqlite3_bind_parameter_index(pTest, "$archiveFile"))>0
){
sqlite3_bind_text(pTest, j, pAr->zFile, -1, SQLITE_TRANSIENT);
}
j = sqlite3_bind_parameter_index(pTest, "$name");
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
char *z = pAr->azArg[i];
int n = strlen30(z);
int bOk = 0;
while( n>0 && z[n-1]=='/' ) n--;
z[n] = '\0';
|
︙ | | |
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
|
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
|
-
-
-
-
-
-
|
"name",
"mode, sz, datetime(mtime, 'unixepoch'), name"
};
char *zWhere = 0;
sqlite3_stmt *pSql = 0;
int rc;
int j;
rc = arCheckEntries(pAr);
arWhereClause(&rc, pAr, &zWhere);
shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
pAr->zSrcTable, zWhere);
if( rc==SQLITE_OK
&& (j = sqlite3_bind_parameter_index(pSql, "$archiveFile"))>0
){
sqlite3_bind_text(pSql, j, pAr->zFile, -1, SQLITE_TRANSIENT);
}
if( pAr->bDryRun ){
utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
}else{
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
if( pAr->bVerbose ){
char zMode[11];
shellModeToString(zMode, sqlite3_column_int(pSql, 0));
|
︙ | | |
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
|
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
|
-
-
-
-
|
shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
);
if( rc==SQLITE_OK ){
j = sqlite3_bind_parameter_index(pSql, "$dir");
sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
j = sqlite3_bind_parameter_index(pSql, "$archiveFile");
if( j ){
sqlite3_bind_text(pSql, j, pAr->zFile, -1, SQLITE_STATIC);
}
/* Run the SELECT statement twice. The first time, writefile() is called
** for all archive members that should be extracted. The second time,
** only for the directories. This is because the timestamps for
** extracted directories must be reset after they are populated (as
** populating them changes the timestamp). */
for(i=0; i<2; i++){
|
︙ | | |
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
|
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
|
-
+
+
+
-
+
+
+
-
-
+
+
+
+
+
+
-
+
+
+
+
+
|
** The create command is the same as update, except that it drops
** any existing "sqlar" table before beginning.
*/
static int arCreateOrUpdateCommand(
ArCommand *pAr, /* Command arguments and options */
int bUpdate /* true for a --create. false for --update */
){
const char *zSql = "SELECT name, mode, mtime, data FROM fsdir(?, ?)";
const char *zSql = "SELECT name, mode, mtime, data FROM fsdir($name, $dir)";
const char *zCreate =
"CREATE TABLE IF NOT EXISTS sqlar(\n"
" name TEXT PRIMARY KEY, -- name of the file\n"
" mode INT, -- access permissions\n"
" mtime INT, -- last modification time\n"
" sz INT, -- original file size\n"
" data BLOB -- compressed content\n"
")";
const char *zDrop = "DROP TABLE IF EXISTS sqlar";
const char *zInsert = "REPLACE INTO sqlar VALUES(?,?,?,?,sqlar_compress(?))";
sqlite3_stmt *pStmt = 0; /* Directory traverser */
sqlite3_stmt *pInsert = 0; /* Compilation of zInsert */
int i; /* For iterating through azFile[] */
int j; /* Parameter index */
int rc; /* Return code */
assert( pAr->bZip==0 );
rc = arExecSql(pAr, "SAVEPOINT ar;");
if( rc!=SQLITE_OK ) return rc;
if( bUpdate==0 ){
rc = arExecSql(pAr, zDrop);
if( rc!=SQLITE_OK ) return rc;
}
rc = arExecSql(pAr, zCreate);
if( !pAr->bDryRun ){
shellPrepare(pAr->db, &rc, zInsert, &pInsert);
shellPrepare(pAr->db, &rc, zInsert, &pInsert);
}
shellPrepare(pAr->db, &rc, zSql, &pStmt);
j = sqlite3_bind_parameter_index(pStmt, "$dir");
sqlite3_bind_text(pStmt, 2, pAr->zDir, -1, SQLITE_STATIC);
sqlite3_bind_text(pStmt, j, pAr->zDir, -1, SQLITE_STATIC);
if( pAr->bDryRun ){
utf8_printf(pAr->p->out, "%s;\n", sqlite3_sql(pStmt));
}
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
j = sqlite3_bind_parameter_index(pStmt, "$name");
sqlite3_bind_text(pStmt, 1, pAr->azArg[i], -1, SQLITE_STATIC);
sqlite3_bind_text(pStmt, j, pAr->azArg[i], -1, SQLITE_STATIC);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
int sz;
const char *zName = (const char*)sqlite3_column_text(pStmt, 0);
int mode = sqlite3_column_int(pStmt, 1);
unsigned int mtime = sqlite3_column_int(pStmt, 2);
if( pAr->bVerbose ){
utf8_printf(pAr->p->out, "%s\n", zName);
}
if( pAr->bDryRun ){
utf8_printf(pAr->p->out, "%s;\n", zInsert);
continue;
}
sqlite3_bind_text(pInsert, 1, zName, -1, SQLITE_STATIC);
sqlite3_bind_int(pInsert, 2, mode);
sqlite3_bind_int64(pInsert, 3, (sqlite3_int64)mtime);
if( S_ISDIR(mode) ){
|
︙ | | |
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
|
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
|
+
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
+
-
-
+
+
+
+
+
+
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
|
char **azArg, /* Array of arguments passed to dot command */
int nArg /* Number of entries in azArg[] */
){
ArCommand cmd;
int rc;
rc = arParseCommand(azArg, nArg, &cmd);
if( rc==SQLITE_OK ){
int eDbType = SHELL_OPEN_UNSPEC;
cmd.p = pState;
cmd.db = pState->db;
cmd.zSrcTable = "sqlar";
if( cmd.bZip || pState->openMode==SHELL_OPEN_ZIPFILE ){
if( cmd.zFile==0
cmd.zSrcTable = 0;
if( cmd.zFile ){
eDbType = deduceDatabaseType(cmd.zFile);
}else{
eDbType = pState->openMode;
}
if( eDbType==SHELL_OPEN_ZIPFILE ){
if( cmd.zFile==0 ){
&& sqlite3_table_column_metadata(cmd.db,0,"zip","name",0,0,0,0,0)==SQLITE_OK
){
cmd.zSrcTable = "zip";
cmd.zSrcTable = sqlite3_mprintf("zip");
}else if( cmd.zFile!=0 ){
cmd.zSrcTable = "zipfile($archiveFile)";
}else{
utf8_printf(stderr, "no zip archive file specified\n");
cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
return SQLITE_ERROR;
}
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
utf8_printf(stderr, "zip archives are read-only\n");
return SQLITE_ERROR;
rc = SQLITE_ERROR;
goto end_ar_command;
}
cmd.bZip = 1;
}else if( cmd.zFile ){
int flags;
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
}else{
flags = SQLITE_OPEN_READONLY;
}
cmd.db = 0;
if( cmd.bDryRun ){
utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
}
rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, 0);
rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
if( rc!=SQLITE_OK ){
utf8_printf(stderr, "cannot open file: %s (%s)\n",
cmd.zFile, sqlite3_errmsg(cmd.db)
);
sqlite3_close(cmd.db);
goto end_ar_command;
return rc;
}
sqlite3_fileio_init(cmd.db, 0, 0);
#ifdef SQLITE_HAVE_ZLIB
sqlite3_sqlar_init(cmd.db, 0, 0);
#endif
}
if( cmd.zSrcTable==0 ){
if( sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) ){
utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
rc = SQLITE_ERROR;
goto end_ar_command;
}
cmd.zSrcTable = sqlite3_mprintf("sqlar");
}
switch( cmd.eCmd ){
case AR_CMD_CREATE:
rc = arCreateOrUpdateCommand(&cmd, 0);
break;
case AR_CMD_EXTRACT:
|
︙ | | |
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
|
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
|
-
-
-
-
+
+
+
+
+
-
+
|
break;
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arCreateOrUpdateCommand(&cmd, 1);
break;
}
if( cmd.db!=pState->db ){
sqlite3_close(cmd.db);
}
}
end_ar_command:
if( cmd.db!=pState->db ){
sqlite3_close(cmd.db);
}
}
sqlite3_free(cmd.zSrcTable);
return rc;
}
/* End of the ".archive" or ".ar" command logic
**********************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
|
︙ | | |