** Implementation of .ar "eXtract" command. */
| 22343 | ** Implementation of .ar "eXtract" command. |
| 22344 | */ |
| 22345 | static int arExtractCommand(ArCommand *pAr){ |
| 22346 | const char *zSql1 = |
| 22347 | "SELECT " |
| 22348 | " ($dir || name)," |
| 22349 | " writefile(($dir || name), %s, mode, mtime) " |
| 22350 | "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" |
| 22351 | " AND name NOT GLOB '*..[/\\]*'"; |
| 22352 | |
| 22353 | const char *azExtraArg[] = { |
| 22354 | "sqlar_uncompress(data, sz)", |
| 22355 | "data" |
| 22356 | }; |
| 22357 | |
| 22358 | sqlite3_stmt *pSql = 0; |
| 22359 | int rc = SQLITE_OK; |
| 22360 | char *zDir = 0; |
| 22361 | char *zWhere = 0; |
| 22362 | int i, j; |
| 22363 | |
| 22364 | /* If arguments are specified, check that they actually exist within |
| 22365 | ** the archive before proceeding. And formulate a WHERE clause to |
| 22366 | ** match them. */ |
| 22367 | rc = arCheckEntries(pAr); |
| 22368 | arWhereClause(&rc, pAr, &zWhere); |
| 22369 | |
| 22370 | if( rc==SQLITE_OK ){ |
| 22371 | if( pAr->zDir ){ |
| 22372 | zDir = sqlite3_mprintf("%s/", pAr->zDir); |
| 22373 | }else{ |
| 22374 | zDir = sqlite3_mprintf(""); |
| 22375 | } |
| 22376 | if( zDir==0 ) rc = SQLITE_NOMEM; |
| 22377 | } |
| 22378 | |
| 22379 | shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, |
| 22380 | azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere |
| 22381 | ); |
| 22382 | |
| 22383 | if( rc==SQLITE_OK ){ |
| 22384 | j = sqlite3_bind_parameter_index(pSql, "$dir"); |
| 22385 | sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); |
| 22386 | |
| 22387 | /* Run the SELECT statement twice. The first time, writefile() is called |
| 22388 | ** for all archive members that should be extracted. The second time, |
| 22389 | ** only for the directories. This is because the timestamps for |
| 22390 | ** extracted directories must be reset after they are populated (as |
| 22391 | ** populating them changes the timestamp). */ |
| 22392 | for(i=0; i<2; i++){ |
| 22393 | j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); |
| 22394 | sqlite3_bind_int(pSql, j, i); |
| 22395 | if( pAr->bDryRun ){ |
| 22396 | utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); |
| 22397 | }else{ |
| 22398 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ |
| 22399 | if( i==0 && pAr->bVerbose ){ |
| 22400 | utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); |
| 22401 | } |
| 22402 | } |
no test coverage detected