/* ** Copyright (c) 2014 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** This program is distributed in the hope that it will be useful, ** but without any warranty; without even the implied warranty of ** merchantability or fitness for a particular purpose. ** ** Author contact information: ** drh@sqlite.org */ #include "sqlite3.h" #include #include #include #include /* ** Show a help message and quit. */ static void showHelp(const char *argv0){ fprintf(stderr, "Usage: %s [options] archive [files...]\n", argv0); fprintf(stderr, "Options:\n" " -l List files in archive\n" " -x Extract files from archive\n" " -d Drop files from archive\n" ); exit(1); } /* ** The database schema: */ static const char zSchema[] = "CREATE TABLE IF NOT EXISTS sar(\n" " filename TEXT PRIMARY KEY,\n" " sz INT,\n" " data BLOB\n" ");" ; /* ** Prepared statement used for inserts */ static sqlite3_stmt *pIns = 0; /* ** Open database connection */ static sqlite3 *db = 0; /* ** Close the database */ static void db_close(int commitFlag){ if( pIns ){ sqlite3_finalize(pIns); pIns = 0; } if( db ){ if( commitFlag ){ sqlite3_exec(db, "COMMIT", 0, 0, 0); }else{ sqlite3_exec(db, "ROLLBACK", 0, 0, 0); } sqlite3_close(db); db = 0; } } /* ** Panic message */ static void errorMsg(const char *zFormat, ...){ va_list ap; va_start(ap, zFormat); vfprintf(stderr, zFormat, ap); va_end(ap); db_close(0); exit(1); } /* ** Open the database. */ static void db_open(const char *zArchive, int writeFlag){ int rc; int fg; if( writeFlag ){ fg = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; }else{ fg = SQLITE_OPEN_READONLY; } rc = sqlite3_open_v2(zArchive, &db, fg, 0); if( rc ) errorMsg("Cannot open archive [%s]: %s\n", zArchive, sqlite3_errmsg(db)); sqlite3_exec(db, "BEGIN", 0, 0, 0); sqlite3_exec(db, zSchema, 0, 0, 0); } /* ** Add a file to the database */ static void add_file( const char *zFilename /* Name of file to add */ ){ FILE *in; long sz; char *zIn; char *zCompr; uLongf nCompr; int rc; in = fopen(zFilename, "rb"); if( in==0 ) return; fseek(in, 0, SEEK_END); sz = ftell(in); zIn = sqlite3_malloc( sz+1 ); if( zIn==0 ) errorMsg("out of memory\n"); rewind(in); fread(zIn, sz, 1, in); fclose(in); if( pIns==0 ){ rc = sqlite3_prepare_v2(db, "REPLACE INTO sar(filename,sz,data) VALUES(?1,?2,?3)", -1, &pIns, 0); if( rc ) errorMsg("%s\n", sqlite3_errmsg(db)); } sqlite3_bind_text(pIns, 1, zFilename, -1, SQLITE_STATIC); sqlite3_bind_int(pIns, 2, sz); nCompr = 13 + sz + (sz+999)/1000; zCompr = sqlite3_malloc( nCompr); if( zCompr==0 ) errorMsg("out of memory\n"); rc = uncompress(zCompr, &nCompr, zIn, sz); if( rc!=Z_OK ) errorMsg("Cannot compress %s\n", zFilename); sqlite3_free(zIn); sqlite3_bind_blob(pIns, 3, zCompr, nCompr, sqlite3_free); rc = sqlite3_step(pIns); if( rc!=SQLITE_DONE ){ errorMsg("Insert failed for %s: %s\n", zFilename, sqlite3_errmsg(db)); } sqlite3_reset(pIns); } int main(int argc, char **argv){ const char *zArchive = 0; char **azFiles = 0; int nFiles = 0; int listFlag = 0; int extractFlag = 0; int i; sqlite3 *db; if( sqlite3_strglob("*/unsar", argv[0])==0 ){ extractFlag = 1; } for(i=1; i