SQLite Archiver
Artifact Content
Not logged in

Artifact d69b6804a34d499063ff5f4991709291d805c059:


/*
** 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 <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <zlib.h>

/*
** 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<argc; i++){
    if( argv[i][0]=='-' ){
      if( strcmp(argv[i],"-l")==0 ){
        listFlag = 1;
      }else if( strcmp(argv[i],"-x")==0 ){
        extractFlag = 1;
      }else{
        showHelp(argv[0]);
      }
    }else if( zArchive==0 ){
      zArchive = argv[i];
    }else{
      azFiles = &argv[i];
      nFiles = argc - i;
      break;
    }
  }
  if( zArchive==0 ) showHelp(argv[0]);
  if( listFlag ){
  }else if( extractFlag ){
  }else{
    if( azFiles==0 ) showHelp(argv[0]);
    db_open(zArchive, 1);
    for(i=0; i<nFiles; i++){
      add_file(argv[i]);
    }
    db_close(1);
  }
  return 0;
}