"Fossies" - the Fresh Open Source Software Archive

Member "unipkg-0.6.5/unipkglib/unipkg-sqlite.c" (16 Dec 2005, 15666 Bytes) of package /linux/privat/old/unipkg-0.6.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 /******************************************************************************\
    2 *                                                                              *
    3 * UNIPKG (c) iSteve <isteve@bofh.cz>, 2005                                     *
    4 *                                                                              *
    5 * Universal PacKaGer.                                                          *
    6 * Licensed under GNU/GPL - if you don't like the software, fix it!             *
    7 *                                                                              *
    8 \******************************************************************************/
    9 
   10 ///////////////////////////////////////////////////////////////////////////////
   11 //                                                                           //
   12 // B A S E   I N C L U S I O N S   A N D   D E F I N I T I O N S             //
   13 //                                                                           //
   14 ///////////////////////////////////////////////////////////////////////////////
   15 #define _GNU_SOURCE
   16 #include <stdlib.h>
   17 #include <stdio.h>
   18 #include <stdarg.h>
   19 #include <string.h>
   20 #include <unistd.h>
   21 #include <fnmatch.h>
   22 #include <errno.h>
   23 #include <dlfcn.h>
   24 #include <libgen.h>
   25 #include <dirent.h>
   26 
   27 #include <sqlite3.h>
   28 
   29 #include <sys/stat.h>
   30 #include <sys/mman.h>
   31 #include <sys/types.h>
   32 
   33 #include "../common.h"
   34 
   35 #define BUSYSLEEP 350
   36 
   37 typedef struct {
   38     sqlite3_stmt        *read;
   39     sqlite3_stmt        *write;
   40     sqlite3_stmt        *write_file;
   41     sqlite3_stmt        *find_name;
   42     sqlite3_stmt        *find_file;
   43     sqlite3_stmt        *find_name_file;
   44     
   45     sqlite3_stmt        *begin, *end;
   46 } tdbcalls;
   47 
   48 typedef struct {
   49     sqlite3         *dbid;      // db handle
   50     tdbcalls            dbcalls;
   51     unsigned long   lpkg;       // Last read package
   52     int             writeable;  // Can we write?
   53 } dbhandle;
   54 
   55 typedef struct {
   56     pkginfo         *pinfo;
   57     dbhandle            *dhandle;
   58     int             update;
   59 } callbackhandle;
   60 
   61 
   62 ///////////////////////////////////////////////////////////////////////////////
   63 //                                                                           //
   64 // B A S E   F U N C T I O N S                                               //
   65 //                                                                           //
   66 ///////////////////////////////////////////////////////////////////////////////
   67 
   68 // SWITCHCOLNAME()
   69 //
   70 // Identifies the column name.
   71 //
   72 // Parameters:
   73 //   the column name
   74 //
   75 // Return value:
   76 //   0 if no match
   77 //   1 if package name
   78 //   2 if package version
   79 //   3 if package description
   80 //   4 if preinst
   81 //   5 if postinst
   82 //   6 if preremove
   83 //   7 if postremove
   84 static int switchcolname(char *colname) {
   85     if (colname == NULL) { return 0; }
   86     if (!strcmp(colname, "name")) { return 1; }
   87     if (!strcmp(colname, "version")) { return 2; }
   88     if (!strcmp(colname, "description")) { return 3; }
   89     
   90     if (!strcmp(colname, "preinst")) { return 4; }
   91     if (!strcmp(colname, "postinst")) { return 5; }
   92     if (!strcmp(colname, "preremove")) { return 6; }
   93     if (!strcmp(colname, "postremove")) { return 7; }
   94     
   95     if (!strcmp(colname, "id")) { return 10; }
   96     return 0;
   97 }
   98 
   99 ///////////////////////////////////////////////////////////////////////////////
  100 //                                                                           //
  101 // A P I   F U N C T I O N S                                                 //
  102 //                                                                           //
  103 ///////////////////////////////////////////////////////////////////////////////
  104 
  105 void *opendb(char *path) {
  106     dbhandle            *reval;
  107     int             err;
  108     
  109     reval = malloc(sizeof(dbhandle));
  110     if (sqlite3_open(path, &reval->dbid)) { 
  111         free(reval); 
  112         return NULL; 
  113     }
  114     reval->lpkg = 0;
  115     reval->writeable = 1;
  116     
  117     // Half a second busy timeout wait.
  118     sqlite3_busy_timeout(reval->dbid, 500);
  119     err = sqlite3_exec(reval->dbid, "CREATE TABLE packages ("
  120                                     "id INTEGER PRIMARY KEY, "
  121                                     "name STRING NULL, "
  122                                     "version STRING NULL, "
  123                                     "description STRING NULL, "
  124                                     "preinst BLOB NULL, postinst BLOB NULL, preremove BLOB NULL, postremove BLOB NULL"
  125                                 "); "
  126                                 "CREATE TABLE files ("
  127                                     "id INTEGER PRIMARY KEY, "
  128                                     "filename STRING NULL, "
  129                                     "pkgid INTEGER"
  130                                 ");", NULL, NULL, NULL);
  131         
  132     err = sqlite3_exec(reval->dbid, "PRAGMA short_column_names; PRAGMA synchronous = FULL;", NULL, NULL, NULL);
  133     if (err) {
  134         free(reval);
  135         return NULL;
  136     }
  137 
  138     //sqlite3_prepare(reval->dbid, ";", -1, &reval->dbcalls.write, NULL);
  139     
  140     sqlite3_prepare(reval->dbid, "INSERT INTO packages ("
  141                                 "name, version, description, preinst, postinst, preremove, postremove"
  142                             ") VALUES ("
  143                                 "?, ?, ?, ?, ?, ?, ?"
  144                             ");", -1, &reval->dbcalls.write, NULL);
  145     
  146     sqlite3_prepare(reval->dbid, "INSERT INTO files ("
  147                                 "filename, pkgid"
  148                             ") VALUES ("
  149                                 "?, ?"
  150                             ");", -1, &reval->dbcalls.write_file, NULL);
  151     
  152     return reval;
  153 }
  154 
  155 void rewinddb(dbhandle *handle) {
  156     handle->lpkg=0;
  157 }
  158 
  159 int iswriteable(dbhandle *handle) {
  160     return handle->writeable;
  161 }
  162 
  163 int closedb(dbhandle *handle) {
  164     sqlite3_close(handle->dbid);
  165     free(handle);
  166     return 0;
  167 }
  168 
  169 int readpkg(dbhandle *handle, pkginfo *pinfo) {
  170     return 1;
  171 }
  172 
  173 int writepkg(dbhandle *handle, pkginfo *pinfo) {
  174     unsigned long   i;
  175     unsigned long   lastid;
  176     char            *foo;
  177 
  178     foo = sqlite3_mprintf("INSERT INTO packages ("
  179                                 "name, version, description, preinst, postinst, preremove, postremove"
  180                             ") VALUES ("
  181                                 "'%q', '%q', '%q', '%q', '%q', '%q', '%q'"
  182                             ");", pinfo->name, pinfo->version, pinfo->description, 
  183                             pinfo->preinst.data, pinfo->postinst.data, pinfo->prerm.data, pinfo->postrm.data);
  184     sqlite3_exec(handle->dbid, foo, NULL, NULL, NULL);
  185 /*  sqlite3_bind_text(handle->dbcalls.write, 1, pinfo->name, strlen(pinfo->name), SQLITE_TRANSIENT);
  186     sqlite3_bind_text(handle->dbcalls.write, 2, pinfo->version, strlen(pinfo->version), SQLITE_TRANSIENT);
  187     sqlite3_bind_text(handle->dbcalls.write, 3, pinfo->description, strlen(pinfo->description), SQLITE_TRANSIENT);
  188     
  189     sqlite3_bind_blob(handle->dbcalls.write, 4, pinfo->preinst.data, pinfo->preinst.len, SQLITE_TRANSIENT);
  190     sqlite3_bind_blob(handle->dbcalls.write, 5, pinfo->postinst.data, pinfo->postinst.len, SQLITE_TRANSIENT);
  191     sqlite3_bind_blob(handle->dbcalls.write, 6, pinfo->prerm.data, pinfo->prerm.len, SQLITE_TRANSIENT);
  192     sqlite3_bind_blob(handle->dbcalls.write, 7, pinfo->postrm.data, pinfo->postrm.len, SQLITE_TRANSIENT);
  193     
  194     sqlite3_step(handle->dbcalls.write);*/
  195     
  196     lastid = sqlite3_last_insert_rowid(handle->dbid);
  197 //  sqlite3_reset(handle->dbcalls.write);
  198 
  199 //  sqlite3_exec(handle->dbid, "BEGIN;", NULL, NULL, NULL);
  200 /*  sqlite3_prepare(handle->dbid, "INSERT INTO files ("
  201                                 "filename, pkgid"
  202                             ") VALUES ("
  203                                 "?, ?"
  204                             ");", -1, &handle->dbcalls.write_file, NULL);
  205     
  206     sqlite3_bind_int64(handle->dbcalls.write_file, 2, lastid);*/
  207     sqlite3_exec(handle->dbid, "BEGIN;", NULL, NULL, NULL);
  208     for (i = 0; i < pinfo->filecount; i++) {
  209         foo = sqlite3_mprintf("INSERT INTO files (filename, pkgid) VALUES ('%q', '%i');", pinfo->files[i].name, lastid);
  210         sqlite3_exec(handle->dbid, foo, NULL, NULL, NULL);
  211         sqlite3_free(foo);
  212         //fprintf(stderr, " Now %s\n", pinfo->files[i].name);*/
  213 /*      sqlite3_bind_text(handle->dbcalls.write_file, 1, pinfo->files[i].name, strlen(pinfo->files[i].name), SQLITE_TRANSIENT);
  214         sqlite3_step(handle->dbcalls.write_file);
  215         sqlite3_reset(handle->dbcalls.write_file);*/
  216     }
  217     //sqlite3_reset(handle->dbcalls.write_file);
  218 //  sqlite3_finalize(handle->dbcalls.write_file);
  219     sqlite3_exec(handle->dbid, "COMMIT; END;", NULL, NULL, NULL);
  220     
  221     return 0;
  222 }
  223 
  224 int findpkg(dbhandle *handle, pkginfo needle, pkginfo *reval, int matchtype) {
  225     return 1;
  226 }
  227 /*void *opendb(char *path) {
  228     dbhandle            *reval;
  229     unsigned long   i;
  230     int             rv;
  231     
  232     reval = malloc(sizeof(dbhandle));
  233     
  234     if (sqlite3_open(path, &reval->dbid)) { free(reval); return NULL; }
  235     reval->lpkg = 0;
  236     
  237     // I HATE THIS HACK ////////////////////////
  238     // We create a dummy table and drop it /////
  239     // afterwards, to check if we can write ////
  240     // Damn, there must be a better way. ///////
  241     i=0;
  242     do {
  243         rv = sqlite3_nobusy_exec_printf(reval->dbid, "CREATE TABLE testtable%02ld (id int); DROP TABLE testtable%02ld;", NULL, NULL, NULL, i, i);
  244         i++;
  245     } while ((rv != 0) && (rv != 8) && (i < 100));
  246     
  247     reval->writeable = 0;
  248     switch (rv) {
  249         case 0:
  250             reval->writeable = 1;
  251             break;
  252         case 8:
  253             reval->writeable = 0;
  254             break;
  255         default:
  256             sqlite3_close(reval->dbid);
  257             free(reval);
  258             return NULL;
  259     }
  260     // END OF UGLY HACK ///////////
  261 
  262     // This will fail if there are tables already... if there are of diferent format, bad luck
  263     sqlite3_nobusy_exec(reval->dbid, "CREATE TABLE packages (id INTEGER PRIMARY KEY, name STRING NULL, version STRING NULL, description STRING NULL, preinst STRING NULL, postinst STRING NULL, preremove STRING NULL, postremove STRING NULL); CREATE TABLE files (id INTEGER PRIMARY KEY, filename STRING NULL, pkgid INTEGER);", NULL, NULL, NULL);
  264     sqlite3_nobusy_exec(reval->dbid, "PRAGMA short_column_names;", NULL, NULL, NULL);
  265     
  266     return reval;
  267 }
  268 void rewinddb(void *handle) {
  269     ((dbhandle*)handle)->lpkg=0;
  270 }
  271 int iswriteable(void *handle) {
  272     return ((dbhandle*)handle)->writeable;
  273 }
  274 int closedb(void *handle) {
  275     sqlite3_close(((dbhandle*)handle)->dbid);
  276     free((dbhandle*)handle);
  277     return 0;   
  278 }
  279 
  280 // READPKG_PKG_CALLBACK()
  281 //
  282 // Parses data returned by sql query asking for package info and feeds it
  283 // into package descripting structure within the dataptr.
  284 //
  285 // Return value and parameters viz sqlite3_callback
  286 static int readpkg_pkg_callback(void *dataptr, int argc, char **argv, char **azColName){
  287     int i;
  288     callbackhandle  *cbh;
  289     
  290     cbh = (callbackhandle*)dataptr;
  291     cbh->update = 1;
  292     for (i=0; i<argc; i++) {
  293         switch (switchcolname(azColName[i])) {
  294             case 1:
  295                 cbh->pinfo->name = strdup(argv[i]);
  296                 break;
  297             case 2:
  298                 cbh->pinfo->version = strdup(argv[i]);
  299                 break;
  300             case 3:
  301                 cbh->pinfo->description = strdup(argv[i]);
  302                 break;
  303             
  304             case 4:
  305                 if (strcmp(argv[i], "(NULL)")) {    // This is probably not very safe.
  306                     cbh->pinfo->preinst = strdup(argv[i]);
  307                 }
  308                 break;
  309             case 5:
  310                 if (strcmp(argv[i], "(NULL)")) {
  311                     cbh->pinfo->postinst = strdup(argv[i]);
  312                 }
  313                 break;
  314             case 6:
  315                 if (strcmp(argv[i], "(NULL)")) {
  316                     cbh->pinfo->prerm = strdup(argv[i]);
  317                 }
  318                 break;
  319             case 7:
  320                 if (strcmp(argv[i], "(NULL)")) {
  321                     cbh->pinfo->postrm = strdup(argv[i]);
  322                 }
  323                 break;
  324             
  325             case 10:
  326                 cbh->dhandle->lpkg = strtoul(argv[i], NULL, 10);
  327                 break;
  328         }
  329     }
  330     return 0;
  331 }
  332 
  333 // READPKG_PKG_CALLBACK()
  334 //
  335 // Parses data returned by sql query asking for package file list and feeds it
  336 // into package descripting structure within the dataptr.
  337 //
  338 // Return value and parameters viz sqlite3_callback
  339 static int readpkg_file_callback(void *dataptr, int argc, char **argv, char **azColName){
  340     int i;
  341     callbackhandle  *cbh;
  342     
  343     cbh = (callbackhandle*)dataptr;
  344     cbh->update = 1;
  345     for (i=0; i<argc; i++) {
  346         if (!strcmp(azColName[i], "filename")) {
  347             cbh->pinfo->files = realloc(cbh->pinfo->files, sizeof(char*) * (cbh->pinfo->filecount + 1));
  348             cbh->pinfo->files[cbh->pinfo->filecount] = strdup(argv[i]);
  349             cbh->pinfo->filecount++;
  350         }
  351     }
  352     return 0;
  353 }
  354 int readpkg(void *handle, pkginfo *pinfo) {
  355     callbackhandle  cbh;
  356     
  357     cbh.dhandle = (dbhandle*)handle;
  358     cbh.pinfo = pinfo;
  359     cbh.update = 0;
  360     sqlite3_nobusy_exec_printf(((dbhandle*)handle)->dbid, "SELECT * FROM packages WHERE id >= %ld ORDER BY id ASC LIMIT 1;", readpkg_pkg_callback, (void *)(&cbh), NULL, ((dbhandle*)handle)->lpkg);
  361     if (!cbh.update){
  362         ((dbhandle*)handle)->lpkg = 0;
  363         return 1;
  364     }
  365 
  366     // lpkg now contains the id of the currently checked pkg
  367     sqlite3_nobusy_exec_printf(((dbhandle*)handle)->dbid, "SELECT * FROM files WHERE pkgid = %ld;", readpkg_file_callback, (void *)(&cbh), NULL, ((dbhandle*)handle)->lpkg);
  368     
  369     ((dbhandle*)handle)->lpkg++;
  370     return 0;
  371 }
  372 int writepkg(void *handle, pkginfo *pinfo) {
  373     int lastid;
  374     unsigned long   i;
  375 
  376     if (sqlite3_nobusy_exec_printf(((dbhandle*)handle)->dbid, "INSERT INTO packages (name, version, description, preinst, postinst, preremove, postremove) VALUES ('%q', '%q', '%q', '%q', '%q', '%q', '%q');", NULL, NULL, NULL, pinfo->name, pinfo->version, pinfo->description, pinfo->preinst, pinfo->postinst, pinfo->prerm, pinfo->postrm) != SQLITE_OK) {
  377         return 1;
  378     }
  379 
  380     lastid = sqlite3_last_insert_rowid(((dbhandle*)handle)->dbid);
  381     
  382     for (i=0; i<pinfo->filecount; i++) {
  383         sqlite3_nobusy_exec_printf(((dbhandle*)handle)->dbid, "INSERT INTO files (filename, pkgid) VALUES ('%q', %ld);", NULL, NULL, NULL, pinfo->files[i], lastid);
  384     }
  385     
  386     return 0;
  387 }
  388 int delpkg(void *handle, char *pneedle) {
  389     return sqlite3_nobusy_exec_printf(((dbhandle*)handle)->dbid, "DELETE FROM files WHERE pkgid = ( SELECT id FROM packages WHERE name GLOB '%q' ); DELETE FROM packages WHERE name GLOB '%q';", NULL, NULL, NULL, pneedle, pneedle);
  390 }
  391 
  392 // FINDPKG_PKG_CALLBACK()
  393 //
  394 // Checks whether a match is for given sql query, if so, reads full package
  395 // information using readpkg.
  396 //
  397 // Return value and parameters viz sqlite3_callback
  398 static int findpkg_callback(void *dataptr, int argc, char **argv, char **azColName){
  399     callbackhandle  *cbh;
  400     pkginfo         *tmppinfo;
  401     
  402     cbh = (callbackhandle*)dataptr;
  403     if ((!strcmp(azColName[0], "id")) || (!strcmp(azColName[0], "pkgid"))) {
  404         cbh->dhandle->lpkg = strtoul(argv[0], NULL, 10);
  405         if (cbh->pinfo == NULL) {
  406             tmppinfo = malloc(sizeof(pkginfo));
  407         } else {
  408             tmppinfo = cbh->pinfo;
  409         }
  410         cbh->update = readpkg((void*)cbh->dhandle, tmppinfo) ? 0 : 1;
  411         if (cbh->pinfo == NULL) {
  412             freepinfo(tmppinfo);
  413             free(tmppinfo);
  414         }
  415     }
  416     
  417     return 0;
  418 }
  419 int findpkg(void *handle, pkginfo needle, pkginfo *reval, int matchtype) {
  420     char                        *sqlbuf, *buf;
  421     unsigned long   i, sqlbuflen;
  422     callbackhandle  cbh;
  423     pkginfo                 tmppinfo;
  424 
  425     // We first get the id of the package, then readpkg it by editing lpkg.
  426     if ((needle.filecount == 0) && (matchtype & MATCH_FILE) && (!(matchtype & MATCH_NAME))) {
  427         return 0;
  428     }
  429     
  430     sqlbuf = NULL;
  431     if ((matchtype & MATCH_NAME) && (!(matchtype & MATCH_FILE))) {
  432         sqlbuf = sqlite3_mprintf("SELECT id FROM packages WHERE id >= %ld AND name GLOB '%q' ORDER BY id ASC LIMIT 1;", ((dbhandle*)handle)->lpkg, needle.name);
  433     } else if ((matchtype & MATCH_FILE) && (!(matchtype & MATCH_NAME))) {
  434         sqlbuf = sqlite3_mprintf("SELECT pkgid FROM files WHERE pkgid >= %ld AND ( ", ((dbhandle*)handle)->lpkg);
  435         sqlbuflen = strlen(sqlbuf) + 1;
  436         for (i=0; i<needle.filecount; i++) {
  437             buf = sqlite3_mprintf("filename GLOB '%q' OR ", needle.files[i]);           
  438             sqlbuflen += strlen(buf) + 1;
  439             sqlbuf = realloc(sqlbuf, sqlbuflen);
  440             strcat(sqlbuf, buf);
  441             sqlite3_free(buf);
  442         }
  443         sqlbuflen += 18;
  444         sqlbuf = realloc(sqlbuf, sqlbuflen);
  445         strcat(sqlbuf, " 1=0 ) LIMIT;1");
  446     } else if ((matchtype & MATCH_NAME) && (matchtype & MATCH_FILE)) {
  447         sqlbuf = sqlite3_mprintf("SELECT pkgid FROM files WHERE packages.name GLOB '%q' AND packages.id = files.pkgid AND pkgid >= %ld AND ( ", needle.name, ((dbhandle*)handle)->lpkg);
  448         sqlbuflen = strlen(sqlbuf) + 1;
  449         for (i=0; i<needle.filecount; i++) {
  450             buf = sqlite3_mprintf("filename GLOB '%q' OR ", needle.files[i]);           
  451             sqlbuflen += strlen(buf) + 1;
  452             sqlbuf = realloc(sqlbuf, sqlbuflen);
  453             strcat(sqlbuf, buf);
  454             sqlite3_free(buf);
  455         }
  456         sqlbuflen += 18;
  457         sqlbuf = realloc(sqlbuf, sqlbuflen);
  458         strcat(sqlbuf, " 1=0 ) LIMIT 1;");
  459     }
  460     
  461     cbh.dhandle = (dbhandle*)handle;
  462     cbh.pinfo = &tmppinfo;
  463     cbh.update = 0;
  464     sqlite3_nobusy_exec(((dbhandle*)handle)->dbid, sqlbuf, findpkg_callback, (void *)(&cbh), NULL);
  465     sqlite3_free(sqlbuf);
  466     
  467     if (cbh.update == 0) { 
  468         return 0;
  469     }
  470     
  471     if ((!strcmp(reval->name, needle.name)) && (matchtype & MATCH_OVRWR)) {
  472         return -1;
  473     } else {
  474         return 1;
  475     }
  476 }
  477 */