SQLite Archiver

Check-in [f563beec00]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Rename the program from "SAR" to "SFA" to avoid a name collision with the System Activity Report (sar) utility from Solaris.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f563beec009360d32a9e18685f60908f387528b7
User & Date: drh 2014-05-15 11:52:23
Context
2014-05-15
11:55
Change the title on the README.md page. check-in: 3d0e7db437 user: drh tags: trunk
11:52
Rename the program from "SAR" to "SFA" to avoid a name collision with the System Activity Report (sar) utility from Solaris. check-in: f563beec00 user: drh tags: trunk
2014-04-07
13:49
Fix typos in the documentation. check-in: d6387bdf60 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.

     1      1   #!/bin/make
     2      2   
     3      3   CC = gcc -g -I.
     4      4   ZLIB = -lz
     5      5   SQLITE_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
     6      6   
     7         -all: sar
            7  +all: sfa
     8      8   	
     9      9   
    10         -sar:	sar.c sqlite3.o
    11         -	$(CC) -o sar sar.c sqlite3.o $(ZLIB)
           10  +sfa:	sfa.c sqlite3.o
           11  +	$(CC) -o sfa sfa.c sqlite3.o $(ZLIB)
    12     12   
    13     13   sqlite3.o:	sqlite3.c sqlite3.h
    14     14   	$(CC) -c sqlite3.c $(SQLITE_OPT) sqlite3.c

Changes to README.md.

     1      1   <h1 align="center">SAR - SQLite Archiver</h1>
     2      2   
     3         -This repository contains sources for a proof-of-concept "SQLite Archiver"
     4         -program.  This program (named "sar") operates much like "zip", except that
            3  +This repository contains sources for a proof-of-concept "SQLite File Archiver"
            4  +program.  This program (named "sfa") operates much like "zip", except that
     5      5   the compressed archive it builds is stored in an SQLite database instead
     6      6   of a ZIP archive.
     7      7   
     8      8   The motivation for this is to see how much larger an SQLite database file
     9      9   is compared to a ZIP archive containing the same content.  The answer depends
    10     10   on the filenames, but 2% seems to be a reasonable guess.  In other words,
    11     11   storing files as compressed blobs in an SQLite database file results in a 
................................................................................
    17     17   On unix, just type "make".  The SQLite sources are included.  The zlib
    18     18   compression library is needed to build.
    19     19   
    20     20   ## Usage
    21     21   
    22     22   To create an archive:
    23     23   
    24         -        sar ARCHIVE FILES...
           24  +        sfa ARCHIVE FILES...
    25     25   
    26     26   All files named in FILES... will be added to the archive.  If another file
    27     27   with the same name already exists in the archive, it is replaced.  If any
    28     28   of the named FILES is a directory, that directory is scanned recursively.
    29     29   
    30     30   To see the contents of an archive:
    31     31   
    32         -        sar -l ARCHIVE
           32  +        sfa -l ARCHIVE
    33     33   
    34     34   To extract the contents of an archive:
    35     35   
    36         -        sar -x ARCHIVE [FILES...]
           36  +        sfa -x ARCHIVE [FILES...]
    37     37   
    38     38   If a FILES argument is provided, then only the named files are extracted.
    39     39   Without a FILES argument, all files are extracted.
    40     40   
    41     41   All commands can be supplemented with -v for verbose output. For example:
    42     42   
    43         -        sar -v ARCHIVE FILES..
    44         -        sar -lv ARCHIVE
    45         -        sar -xv ARCHIVE
           43  +        sfa -v ARCHIVE FILES..
           44  +        sfa -lv ARCHIVE
           45  +        sfa -xv ARCHIVE
    46     46   
    47     47   File are normally compressed using zlib prior to being stored as BLOBs in
    48     48   the database.  However, if the file is incompressible or if the -n option
    49     49   is used on the command-line, then the file is stored in the database exactly
    50     50   as it appears on disk, without compression.
    51     51       
    52     52   ## Storage
    53     53   
    54     54   The database schema looks like this:
    55     55   
    56         -        CREATE TABLE sar(
           56  +        CREATE TABLE sfa(
    57     57             name TEXT PRIMARY KEY,  -- name of the file
    58     58             mode INT,               -- access permissions
    59     59             mtime INT,              -- last modification time
    60     60             sz INT,                 -- original file size
    61     61             data BLOB               -- compressed content
    62     62           );
    63     63           
    64         -Both directories and empty files have sar.sz==0.  Directories can be
    65         -distinguished from empty files because directories have sar.data IS NULL.
    66         -The file is compressed if length(sar.blob)<sar.sz and is stored
    67         -as plaintext if length(sar.blob)==sar.sz.
           64  +Both directories and empty files have sfa.sz==0.  Directories can be
           65  +distinguished from empty files because directories have sfa.data IS NULL.
           66  +The file is compressed if length(sfa.blob)<sfa.sz and is stored
           67  +as plaintext if length(sfa.blob)==sfa.sz.

Name change from sar.c to sfa.c.

    36     36     exit(1);
    37     37   }
    38     38   
    39     39   /*
    40     40   ** The database schema:
    41     41   */
    42     42   static const char zSchema[] = 
    43         -  "CREATE TABLE IF NOT EXISTS sar(\n"
           43  +  "CREATE TABLE IF NOT EXISTS sfa(\n"
    44     44     "  name TEXT PRIMARY KEY,\n"
    45     45     "  mode INT,\n"
    46     46     "  mtime INT,\n"
    47     47     "  sz INT,\n"
    48     48     "  data BLOB\n"
    49     49     ");"
    50     50   ;
................................................................................
   277    277     check_filename(zFilename);
   278    278     rc = stat(zFilename, &x);
   279    279     if( rc ) errorMsg("no such file or directory: %s\n", zFilename);
   280    280     if( x.st_size>1000000000 ){
   281    281       errorMsg("file too big: %s\n", zFilename);
   282    282     }
   283    283     if( pStmt==0 ){
   284         -    db_prepare("REPLACE INTO sar(name,mode,mtime,sz,data)"
          284  +    db_prepare("REPLACE INTO sfa(name,mode,mtime,sz,data)"
   285    285                  " VALUES(?1,?2,?3,?4,?5)");
   286    286     }
   287    287     zName = zFilename;
   288    288     while( zName[0]=='/' ) zName++;
   289    289     sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
   290    290     sqlite3_bind_int(pStmt, 2, x.st_mode);
   291    291     sqlite3_bind_int64(pStmt, 3, x.st_mtime);
................................................................................
   368    368     int nFiles = 0;
   369    369     int listFlag = 0;
   370    370     int extractFlag = 0;
   371    371     int verboseFlag = 0;
   372    372     int noCompress = 0;
   373    373     int i, j;
   374    374   
   375         -  if( sqlite3_strglob("*/unsar", argv[0])==0 ){
          375  +  if( sqlite3_strglob("*/unsfa", argv[0])==0 ){
   376    376       extractFlag = 1;
   377    377     }
   378    378     for(i=1; i<argc; i++){
   379    379       if( argv[i][0]=='-' ){
   380    380         for(j=1; argv[i][j]; j++){
   381    381           switch( argv[i][j] ){
   382    382             case 'l':   listFlag = 1;    break;
................................................................................
   398    398     if( zArchive==0 ) showHelp(argv[0]);
   399    399     if( listFlag ){
   400    400       int rc;
   401    401       db_open(zArchive, 0);
   402    402       if( verboseFlag ){
   403    403         db_prepare(
   404    404             "SELECT name, sz, length(data), mode, datetime(mtime,'unixepoch')"
   405         -          " FROM sar ORDER BY name"
          405  +          " FROM sfa ORDER BY name"
   406    406         );
   407    407         while( sqlite3_step(pStmt)==SQLITE_ROW ){
   408    408           printf("%10d %10d %03o %s %s\n", 
   409    409                  sqlite3_column_int(pStmt, 1),
   410    410                  sqlite3_column_int(pStmt, 2),
   411    411                  sqlite3_column_int(pStmt, 3)&0777,
   412    412                  sqlite3_column_text(pStmt, 4),
   413    413                  sqlite3_column_text(pStmt, 0));
   414    414         }
   415    415       }else{
   416    416         db_prepare(
   417         -          "SELECT name FROM sar ORDER BY name"
          417  +          "SELECT name FROM sfa ORDER BY name"
   418    418         );
   419    419         while( sqlite3_step(pStmt)==SQLITE_ROW ){
   420    420           printf("%s\n", sqlite3_column_text(pStmt,0));
   421    421         }
   422    422       }
   423    423       db_close(1);
   424    424     }else if( extractFlag ){
................................................................................
   427    427       db_open(zArchive, 0);
   428    428       if( nFiles ){
   429    429         NameList x;
   430    430         x.azName = azFiles;
   431    431         x.nName = nFiles;
   432    432         sqlite3_create_function(db, "name_on_list", 1, SQLITE_UTF8,
   433    433                                 (char*)&x, name_on_list, 0, 0);
   434         -      zSql = "SELECT name, mode, mtime, sz, data FROM sar"
          434  +      zSql = "SELECT name, mode, mtime, sz, data FROM sfa"
   435    435                " WHERE name_on_list(filename)";
   436    436       }else{
   437         -      zSql = "SELECT name, mode, mtime, sz, data FROM sar";
          437  +      zSql = "SELECT name, mode, mtime, sz, data FROM sfa";
   438    438       }
   439    439       db_prepare(zSql);
   440    440       while( sqlite3_step(pStmt)==SQLITE_ROW ){
   441    441         const char *zFN = (const char*)sqlite3_column_text(pStmt, 0);
   442    442         check_filename(zFN);
   443    443         if( zFN[0]=='/' ){
   444    444           errorMsg("absolute pathname: %s\n", zFN);