"Fossies" - the Fresh Open Source Software Archive

Member "unipkg-0.6.5/unipkglib/unipkg-debdb.c" (16 Dec 2005, 16467 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.

    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 
   17 #include <stdlib.h>
   18 #include <stdio.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 <sys/stat.h>
   28 #include <sys/mman.h>
   29 #include <sys/types.h>
   30 
   31 #include "../common.h"
   32 
   33 typedef struct {
   34     char        *fpath, *givenpath;
   35     struct dirent   **namelist;
   36     long        curname;
   37     long        namecount;
   38     void        *statusfilemap;
   39     FILE            *statusfp;
   40     off_t           statussize;
   41 } dbhandle;
   42 
   43 struct treeNode {
   44     struct treeNode *child;
   45     struct treeNode *sibling;
   46     struct treeNode *parent;
   47     char *name;
   48 };
   49 
   50 
   51 ///////////////////////////////////////////////////////////////////////////////
   52 //                                                                           //
   53 // B A S E   F U N C T I O N S                                               //
   54 //                                                                           //
   55 ///////////////////////////////////////////////////////////////////////////////
   56 
   57 // GETCTRLHDR()
   58 //
   59 // Gets a value from debian's control file
   60 //
   61 // Parameters:
   62 //   the whole control file
   63 //   the header we look for
   64 //   the size of the control file
   65 //
   66 // Return value:
   67 //   malloced string
   68 static char *getctrlhdr(char *fullfile, char *hdr, unsigned long size) {
   69     char *start, *end, *tar;
   70     
   71     if ((start = pstrnstr(fullfile, hdr, size, 0)) == NULL) {
   72         return NULL;
   73     }
   74     if (start != fullfile) {    // Is it at the start of the file?
   75         if (*(start-1) != '\n') {   // No? And is it on a new line?
   76             return NULL;            // No? Baibai.
   77         }
   78     }
   79     start = start + strlen(hdr);
   80     
   81     while (*start == ' ') { start++; }  // Skip all spaces after the start, since there may be issues.
   82     
   83     if ((end = pstrnstr(start, "\n", size, 0)) == NULL) {
   84         return NULL;
   85     }
   86     tar = malloc((int)end - (int)start + 1);
   87     strncpy(tar, start, (int)end - (int)start);
   88     tar[(int)end - (int)start] = 0x0;
   89     return tar;
   90 }
   91 
   92 // INFILTER()
   93 //
   94 // Trivial function for scandir, to filter out only *.list files in the
   95 // Debian's /var/lib/dpkg/info dir. Note that the /var/lib/dpkg
   96 // mentioned here (and above) is only for reference, this backend
   97 // takes path just like any other -- see README for details.
   98 //
   99 // Parameters:
  100 //   pointer to dirent structure, containing match
  101 //
  102 // Return value:
  103 //   zero if not matching
  104 //   non-zero if match
  105 static int infilter(const struct dirent *inname) {
  106     return !fnmatch("*.list", inname->d_name, 0);
  107 }
  108 
  109 ///////////////////////////////////////////////////////////////////////////////
  110 //                                                                           //
  111 // A P I   F U N C T I O N S                                                 //
  112 //                                                                           //
  113 ///////////////////////////////////////////////////////////////////////////////
  114 
  115 void *opendb(char *path) {
  116     dbhandle *reval;
  117     struct stat statbuf;
  118     char    *tmppath;
  119     
  120     reval = malloc(sizeof(dbhandle));
  121     reval->givenpath = strdup(path);
  122     reval->fpath = malloc(strlen(path) + 7);
  123     strcpy(reval->fpath, path);
  124     if (path[strlen(path)-1] != '/') { strcat(reval->fpath, "/"); }
  125     strcat(reval->fpath, "info/");
  126     reval->curname = 0;
  127     reval->namecount = scandir(reval->fpath, &reval->namelist, infilter, alphasort);
  128     if (reval -> namecount < 0) {
  129         free(reval->fpath);
  130         free(reval);
  131         return NULL;
  132     }
  133     
  134     tmppath = malloc(strlen(path) + 8);
  135     strcpy(tmppath, path);
  136     if (tmppath[strlen(tmppath)-1] != '/') { strcat(tmppath, "/"); }
  137     strcat(tmppath, "status");
  138     
  139     reval->statusfp = fopen(tmppath, "r");
  140     if (reval->statusfp == NULL) { return NULL; }
  141     fstat(fileno(reval->statusfp), &statbuf);
  142     reval->statussize = statbuf.st_size;
  143     reval->statusfilemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fileno(reval->statusfp), 0);
  144     free(tmppath);
  145     
  146     return reval;
  147 }
  148 
  149 void rewinddb(void *handle) {
  150     ((dbhandle*)handle)->curname = 0;
  151 }
  152 
  153 int iswriteable(void *handle) {
  154     return 0;
  155 }
  156 
  157 int closedb(void *handle) {
  158     long i;
  159     for (i=0; i<((dbhandle*)handle)->namecount; i++) {
  160         free(((dbhandle*)handle)->namelist[i]);
  161     }
  162     free(((dbhandle*)handle)->namelist);
  163     free(((dbhandle*)handle)->fpath);
  164     free(((dbhandle*)handle)->givenpath);
  165     munmap(((dbhandle*)handle)->statusfilemap, ((dbhandle*)handle)->statussize);
  166     fclose(((dbhandle*)handle)->statusfp);
  167     free((dbhandle*)handle);
  168     return 0;
  169 }
  170 
  171 int readpkg(void *handle, pkginfo *pinfo) {
  172     struct stat     statbuf;
  173     FILE                *fp;
  174     char            *buf, *tmpbuf, *fpath;
  175     char            *start, *end;
  176     unsigned long   bufsize;
  177     
  178     if (((dbhandle*)handle)->curname >= ((dbhandle*)handle)->namecount) {
  179         return 1;
  180     }
  181     fpath = malloc(strlen(((dbhandle*)handle)->fpath) + strlen(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name) + 1);
  182     strcpy(fpath, ((dbhandle*)handle)->fpath);
  183     strcat(fpath, ((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  184     
  185     // Set name.
  186     buf = strdup(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  187     end = strrchr(buf, '.');
  188     *end = '\0';
  189         
  190     pinfo->name = strdup(basename(buf));
  191     free(buf);
  192     
  193     
  194     // /var/lib/dpkg/status info
  195     start = ((dbhandle*)handle)->statusfilemap;
  196     do {
  197         end = pstrnstr(start, "\n\n", (unsigned long)(((dbhandle*)handle)->statusfilemap + ((dbhandle*)handle)->statussize - (void*)start), 0);
  198         if (end == NULL) { break; }
  199         //fprintf(stderr, "start: %lx, end: %lx\n", start, end);
  200         buf = strndup(start, end-start);
  201         
  202         tmpbuf = getctrlhdr(buf, "Package:", (unsigned long)(end - start));
  203         if (tmpbuf == NULL) {
  204             free(buf);
  205             start = end + 2;
  206             continue;
  207         }
  208         if (!strcmp(tmpbuf, pinfo->name)) {
  209             free(tmpbuf);
  210             
  211             tmpbuf = getctrlhdr(buf, "Status:", (unsigned long)(end - start));
  212             if (tmpbuf == NULL) {
  213                 free(buf);
  214                 
  215                 // Get new name
  216                 ((dbhandle*)handle)->curname++;
  217                 buf = strdup(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  218                 end = strrchr(buf, '.');
  219                 *end = '\0';
  220                 
  221                 free(pinfo->name);
  222                 
  223                 // Start over with new name.
  224                 pinfo->name = strdup(basename(buf));
  225                 start = ((dbhandle*)handle)->statusfilemap;
  226                 free(buf);
  227                 continue;
  228             } else if (strcmp(tmpbuf, "install ok installed")) {
  229                 free(buf);
  230                 free(tmpbuf);
  231                 
  232                 // Get new name
  233                 ((dbhandle*)handle)->curname++;
  234                 buf = strdup(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  235                 end = strrchr(buf, '.');
  236                 *end = '\0';
  237                 
  238                 // Start over with new name.
  239                 free(pinfo->name);
  240                 pinfo->name = strdup(basename(buf));
  241                 start = ((dbhandle*)handle)->statusfilemap;
  242                 free(buf);
  243                 continue;
  244             } else {
  245                 free(tmpbuf);
  246             }
  247             
  248             pinfo->version = getctrlhdr(buf, "Version:", (unsigned long)(end - start));
  249             if (pinfo->version == NULL) { pinfo->version = strdup("unknown"); }
  250             pinfo->description = getctrlhdr(buf, "Description:", (unsigned long)(end - start));
  251             if (pinfo->description == NULL) { pinfo->description = strdup("Debian package, no description"); }
  252             tmpbuf = getctrlhdr(buf, "Installed-Size:", (unsigned long)(end - start));
  253             if (tmpbuf != NULL) {
  254                 pinfo->pkgsize = strtoul(tmpbuf, NULL, 10) * 1024;
  255                 free(tmpbuf);
  256             }
  257             free(buf);
  258             break;
  259         }
  260         free(buf);
  261         free(tmpbuf);
  262         start = end + 2;
  263     } while(((void*)start - ((dbhandle*)handle)->statusfilemap) < ((dbhandle*)handle)->statussize);
  264     
  265     // reading files preparation
  266     fp = fopen(fpath, "r");
  267     if (fp == NULL) { return 1; }
  268         
  269     // let's read files
  270     pinfo->filecount = 0;
  271     do {
  272         bufsize = 1024;
  273         buf = malloc(bufsize);
  274         while (fgets(buf, bufsize, fp) != NULL) {
  275             if (buf[strnlen(buf, bufsize)-1] == '\n') {
  276                 buf[strnlen(buf, bufsize)-1] = '\0';
  277                 addfile(pinfo, absolutizestr(buf, "/"), F_IRRELEVANT);
  278                 break;
  279             } else {
  280                 bufsize = bufsize * 2;
  281                 buf = realloc(buf, bufsize);
  282             }
  283         }
  284         free(buf);
  285     } while (!feof(fp));
  286     fclose(fp);
  287     
  288     //// SCRIPTS //////////////////////////////////////////////////
  289     buf = malloc(strlen(fpath) + 5);
  290     strncpy(buf, fpath, strlen(fpath) - 4);
  291     buf[strlen(fpath)-5] = '\0';
  292     
  293     free(fpath);
  294     fpath = strdup(buf);
  295     
  296     strcat(buf, ".preinst");
  297     fp = fopen(buf, "r");
  298     if (fp != NULL) {
  299         fstat(fileno(fp), &statbuf);
  300         pinfo->preinst.len = statbuf.st_size;
  301         pinfo->preinst.data = malloc(statbuf.st_size);
  302         if (!fread(pinfo->preinst.data, statbuf.st_size, 1, fp)) {
  303             free(pinfo->preinst.data);
  304             pinfo->preinst.data = NULL;
  305             pinfo->preinst.len = 0;
  306         }
  307         fclose(fp);
  308     }
  309     free(buf);
  310     
  311     buf = malloc(strlen(fpath) + 10);
  312     strcpy(buf, fpath);
  313     strcat(buf, ".postinst");
  314     fp = fopen(buf, "r");
  315     if (fp != NULL) {
  316         fstat(fileno(fp), &statbuf);
  317         pinfo->postinst.len = statbuf.st_size;
  318         pinfo->postinst.data = malloc(statbuf.st_size);
  319         if (!fread(pinfo->postinst.data, statbuf.st_size, 1, fp)) {
  320             free(pinfo->postinst.data);
  321             pinfo->postinst.data = NULL;
  322             pinfo->postinst.len = 0;
  323         }
  324         fclose(fp);
  325     }
  326     free(buf);
  327     
  328     buf = malloc(strlen(fpath) + 7);
  329     strcpy(buf, fpath);
  330     strcat(buf, ".prerm");
  331     fp = fopen(buf, "r");
  332     if (fp != NULL) {
  333         fstat(fileno(fp), &statbuf);
  334         pinfo->prerm.len = statbuf.st_size;
  335         pinfo->prerm.data = malloc(statbuf.st_size);
  336         if (!fread(pinfo->prerm.data, statbuf.st_size, 1, fp)) {
  337             free(pinfo->prerm.data);
  338             pinfo->prerm.data = NULL;
  339             pinfo->prerm.len = 0;
  340         }
  341         fclose(fp);
  342     }
  343     free(buf);
  344     
  345     buf = malloc(strlen(fpath) + 8);
  346     strcpy(buf, fpath);
  347     strcat(buf, ".postrm");
  348     fp = fopen(buf, "r");
  349     if (fp != NULL) {
  350         fstat(fileno(fp), &statbuf);
  351         pinfo->postrm.len = statbuf.st_size;
  352         pinfo->postrm.data = malloc(statbuf.st_size);
  353         if (!fread(pinfo->postrm.data, statbuf.st_size, 1, fp)) {
  354             free(pinfo->postrm.data);
  355             pinfo->postrm.data = NULL;
  356             pinfo->postrm.len = 0;
  357         }
  358         fclose(fp);
  359     }
  360     free(buf);
  361     free(fpath);
  362     //// END OF SCRIPTS /////////////////////////////////////////// /**/
  363 
  364     ((dbhandle*)handle)->curname++;
  365     
  366     // These are various parameters to be used in various cases with the handling scripts.
  367     // They are only given if the script exists.
  368     if (pinfo->preinst.data != NULL) {
  369         pinfo->preinst.parameters[A_IRRELEVANT] = strdup("configure");
  370         pinfo->preinst.parameters[A_UPGRADE] = strdup("upgrade");
  371         pinfo->preinst.parameters[A_DOWNGRADE] = strdup("upgrade");
  372         pinfo->preinst.parameters[A_REINSTALL] = strdup("upgrade");
  373     }
  374 
  375     if (pinfo->postinst.data != NULL) {
  376         pinfo->postinst.parameters[A_IRRELEVANT] = strdup("configure");
  377         pinfo->postinst.parameters[A_UPGRADE] = strdup("upgrade");
  378         pinfo->postinst.parameters[A_DOWNGRADE] = strdup("upgrade");
  379         pinfo->postinst.parameters[A_REINSTALL] = strdup("upgrade");
  380     }
  381 
  382     if (pinfo->prerm.data != NULL) {
  383         pinfo->prerm.parameters[A_IRRELEVANT] = strdup("remove");
  384         pinfo->prerm.parameters[A_REMOVE] = strdup("remove");
  385         pinfo->prerm.parameters[A_UPGRADE] = strdup("upgrade");
  386         pinfo->prerm.parameters[A_DOWNGRADE] = strdup("upgrade");
  387         pinfo->prerm.parameters[A_REINSTALL] = strdup("upgrade");
  388     }
  389 
  390     if (pinfo->postrm.data != NULL) {
  391         pinfo->postrm.parameters[A_IRRELEVANT] = strdup("remove");
  392         pinfo->postrm.parameters[A_REMOVE] = strdup("remove");
  393         pinfo->postrm.parameters[A_UPGRADE] = strdup("upgrade");
  394         pinfo->postrm.parameters[A_DOWNGRADE] = strdup("upgrade");
  395         pinfo->postrm.parameters[A_REINSTALL] = strdup("upgrade");
  396     }
  397     
  398     return 0;
  399 }
  400 
  401 int writepkg(void *handle, pkginfo *pinfo) {
  402     return 1;
  403 }
  404 
  405 int findpkg(void *handle, pkginfo needle, pkginfo *reval, int matchtype) {
  406     char *buf, *fnbuf, *end, *fpath;
  407     FILE *fp;
  408     unsigned long bufsize, i;
  409     
  410     if ((needle.filecount == 0) && (matchtype & MATCH_FILE) && (!(matchtype & MATCH_NAME))) {
  411         // It's senseless to continue -- we only match files, but we have no files to match!
  412         return 0;
  413     }
  414     
  415     while (((dbhandle*)handle)->curname < ((dbhandle*)handle)->namecount) {
  416         if ((matchtype & MATCH_NAME) && (!(matchtype & MATCH_FILE))) { // First check -- packagename.
  417             buf = strdup(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  418             end = strrchr(buf, '.');
  419             *end = '\0';
  420             if (!fnmatch(needle.name, buf, 0)) {
  421                 free(buf);
  422                 if (reval != NULL) { 
  423                     if (readpkg(handle, reval)) {
  424                         continue;
  425                     }
  426                 } else {
  427                     ((dbhandle*)handle)->curname++;
  428                 }
  429                 if (matchtype & MATCH_OVRWR) {
  430                     return -1;
  431                 } else {
  432                     return 1;
  433                 }
  434             } else {
  435                 free(buf);
  436             }
  437         } else if ((matchtype & MATCH_FILE) && (!(matchtype & MATCH_NAME))) { // Second check -- files
  438             fpath = malloc(strlen(((dbhandle*)handle)->fpath) + strlen(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name) + 1);
  439             strcpy(fpath, ((dbhandle*)handle)->fpath);
  440             strcat(fpath, ((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  441             fp = fopen(fpath, "r");
  442             free(fpath);
  443             do {
  444                 bufsize = 1024;
  445                 fnbuf = malloc(bufsize);
  446                 while (fgets(fnbuf, bufsize, fp) != NULL) {
  447                     if (fnbuf[strnlen(fnbuf, bufsize)-1] == '\n') {
  448                         fnbuf[strnlen(fnbuf, bufsize)-1] = '\0';
  449                         
  450                         buf = absolutizestr(fnbuf, "/");
  451                         
  452                         // Check.
  453                         for (i=0; i<needle.filecount; i++) {
  454                             // We do NOT want to match directories.
  455                             if (needle.files[i].flag == F_DIRECTORY) continue;
  456                             if (!fnmatch(needle.files[i].name, buf, 0)) {
  457                                 free(buf);
  458                                 free(fnbuf);
  459                                 if (reval != NULL) { 
  460                                     if (readpkg(handle, reval)) {
  461                                         continue;
  462                                     }
  463                                 } else {
  464                                     ((dbhandle*)handle)->curname++;
  465                                 }
  466                                 fclose(fp);
  467                                 
  468                                 if (matchtype & MATCH_OVRWR) {
  469                                     return -1;
  470                                 } else {
  471                                     return 1;
  472                                 }
  473                             }
  474                         }
  475                         free(buf);
  476                         
  477                         break;
  478                     } else {
  479                         bufsize = bufsize * 2;
  480                         fnbuf = realloc(fnbuf, bufsize);
  481                     }
  482                 }
  483                 free(fnbuf);
  484             } while (!feof(fp));
  485             fclose(fp);
  486         } else if ((matchtype & MATCH_NAME) && (matchtype & MATCH_FILE)) { // Third check, files and packagename
  487             buf = strdup(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  488             end = strrchr(buf, '.');
  489             *end = '\0';
  490             if (!fnmatch(needle.name, buf, 0)) {
  491                 free(buf);
  492                 fpath = malloc(strlen(((dbhandle*)handle)->fpath) + strlen(((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name) + 1);
  493                 strcpy(fpath, ((dbhandle*)handle)->fpath);
  494                 strcat(fpath, ((dbhandle*)handle)->namelist[((dbhandle*)handle)->curname]->d_name);
  495                 fp = fopen(fpath, "r");
  496                 free(fpath);
  497                 do {
  498                     bufsize = 1024;
  499                     fnbuf = malloc(bufsize);
  500                     while (fgets(fnbuf, bufsize, fp) != NULL) {
  501                         if (fnbuf[strnlen(fnbuf, bufsize)-1] == '\n') {
  502                             fnbuf[strnlen(fnbuf, bufsize)-1] = '\0';
  503                             
  504                             buf = absolutizestr(fnbuf, "/");
  505                         
  506                             // Check.
  507                             for (i=0; i<needle.filecount; i++) {
  508                                 // We do NOT want to match directories.
  509                                 if (needle.files[i].flag == F_DIRECTORY) continue;
  510                                 if (!fnmatch(needle.files[i].name, buf, 0)) {
  511                                     free(buf);
  512                                     free(fnbuf);
  513                                     if (reval != NULL) { 
  514                                         if (readpkg(handle, reval)) {
  515                                             continue;
  516                                         }
  517                                     } else {
  518                                         ((dbhandle*)handle)->curname++;
  519                                     }
  520                                     fclose(fp);
  521                                     
  522                                     if (matchtype & MATCH_OVRWR) {
  523                                         return -1;
  524                                     } else {
  525                                         return 1;
  526                                     }
  527                                 }
  528                             }
  529                             free(buf);
  530                         
  531                             break;
  532                         } else {
  533                             bufsize = bufsize * 2;
  534                             fnbuf = realloc(fnbuf, bufsize);
  535                         }
  536                     }
  537                     free(fnbuf);
  538                 } while (!feof(fp));
  539                 fclose(fp);
  540             } else {
  541                 free(buf);
  542             }
  543         }
  544         ((dbhandle*)handle)->curname++;
  545     }
  546     ((dbhandle*)handle)->curname = 0;
  547 
  548     return 0;
  549 }
  550 
  551 int delpkg(void *handle, char *pneedle) {
  552     return 1;
  553 }