** Implementation of .ar "eXtract" command. */
| 16536 | ** Implementation of .ar "eXtract" command. |
| 16537 | */ |
| 16538 | static int arExtractCommand(ArCommand *pAr){ |
| 16539 | const char *zSql1 = |
| 16540 | "SELECT " |
| 16541 | " ($dir || name)," |
| 16542 | " writefile(($dir || name), %s, mode, mtime) " |
| 16543 | "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" |
| 16544 | " AND name NOT GLOB '*..[/\\]*'"; |
| 16545 | |
| 16546 | const char *azExtraArg[] = { |
| 16547 | "sqlar_uncompress(data, sz)", |
| 16548 | "data" |
| 16549 | }; |
| 16550 | |
| 16551 | sqlite3_stmt *pSql = 0; |
| 16552 | int rc = SQLITE_OK; |
| 16553 | char *zDir = 0; |
| 16554 | char *zWhere = 0; |
| 16555 | int i, j; |
| 16556 | |
| 16557 | /* If arguments are specified, check that they actually exist within |
| 16558 | ** the archive before proceeding. And formulate a WHERE clause to |
| 16559 | ** match them. */ |
| 16560 | rc = arCheckEntries(pAr); |
| 16561 | arWhereClause(&rc, pAr, &zWhere); |
| 16562 | |
| 16563 | if( rc==SQLITE_OK ){ |
| 16564 | if( pAr->zDir ){ |
| 16565 | zDir = sqlite3_mprintf("%s/", pAr->zDir); |
| 16566 | }else{ |
| 16567 | zDir = sqlite3_mprintf(""); |
| 16568 | } |
| 16569 | if( zDir==0 ) rc = SQLITE_NOMEM; |
| 16570 | } |
| 16571 | |
| 16572 | shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, |
| 16573 | azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere |
| 16574 | ); |
| 16575 | |
| 16576 | if( rc==SQLITE_OK ){ |
| 16577 | j = sqlite3_bind_parameter_index(pSql, "$dir"); |
| 16578 | sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); |
| 16579 | |
| 16580 | /* Run the SELECT statement twice. The first time, writefile() is called |
| 16581 | ** for all archive members that should be extracted. The second time, |
| 16582 | ** only for the directories. This is because the timestamps for |
| 16583 | ** extracted directories must be reset after they are populated (as |
| 16584 | ** populating them changes the timestamp). */ |
| 16585 | for(i=0; i<2; i++){ |
| 16586 | j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); |
| 16587 | sqlite3_bind_int(pSql, j, i); |
| 16588 | if( pAr->bDryRun ){ |
| 16589 | utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); |
| 16590 | }else{ |
| 16591 | while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ |
| 16592 | if( i==0 && pAr->bVerbose ){ |
| 16593 | utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); |
| 16594 | } |
| 16595 | } |
no test coverage detected