** Implementation of .ar "eXtract" command. */
| 27462 | ** Implementation of .ar "eXtract" command. |
| 27463 | */ |
| 27464 | static int arExtractCommand(ArCommand *pAr){ |
| 27465 | const char *zSql1 = |
| 27466 | "SELECT " |
| 27467 | " ($dir || name)," |
| 27468 | " writefile(($dir || name), %s, mode, mtime) " |
| 27469 | "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" |
| 27470 | " AND name NOT GLOB '*..[/\\]*'"; |
| 27471 | |
| 27472 | const char *azExtraArg[] = { |
| 27473 | "sqlar_uncompress(data, sz)", |
| 27474 | "data" |
| 27475 | }; |
| 27476 | |
| 27477 | sqlite3_stmt *pSql = 0; |
| 27478 | int rc = SQLITE_OK; |
| 27479 | char *zDir = 0; |
| 27480 | char *zWhere = 0; |
| 27481 | int i, j; |
| 27482 | |
| 27483 | /* If arguments are specified, check that they actually exist within |
| 27484 | ** the archive before proceeding. And formulate a WHERE clause to |
| 27485 | ** match them. */ |
| 27486 | rc = arCheckEntries(pAr); |
| 27487 | arWhereClause(&rc, pAr, &zWhere); |
| 27488 | |
| 27489 | if( rc==SQLITE_OK ){ |
| 27490 | if( pAr->zDir ){ |
| 27491 | zDir = sqlite3_mprintf("%s/", pAr->zDir); |
| 27492 | }else{ |
| 27493 | zDir = sqlite3_mprintf(""); |
| 27494 | } |
| 27495 | if( zDir==0 ) rc = SQLITE_NOMEM; |
| 27496 | } |
| 27497 | |
| 27498 | shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, |
| 27499 | azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere |
| 27500 | ); |
| 27501 | |
| 27502 | if( rc==SQLITE_OK ){ |
| 27503 | j = sqlite3_bind_parameter_index(pSql, "$dir"); |
| 27504 | sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); |
| 27505 | |
| 27506 | /* Run the SELECT statement twice. The first time, writefile() is called |
| 27507 | ** for all archive members that should be extracted. The second time, |
| 27508 | ** only for the directories. This is because the timestamps for |
| 27509 | ** extracted directories must be reset after they are populated (as |
| 27510 | ** populating them changes the timestamp). */ |
| 27511 | for(i=0; i<2; i++){ |
| 27512 | j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); |
| 27513 | sqlite3_bind_int(pSql, j, i); |
| 27514 | if( pAr->bDryRun ){ |
| 27515 | sqlite3_fprintf(pAr->out, "%s\n", sqlite3_sql(pSql)); |
| 27516 | }else{ |
| 27517 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ |
| 27518 | if( i==0 && pAr->bVerbose ){ |
| 27519 | sqlite3_fprintf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0)); |
| 27520 | } |
| 27521 | } |
no test coverage detected