"Fossies" - the Fresh Open Source Software Archive

Member "unipkg-0.6.5/unipkglib/unipkg-xmlfile.c" (16 Dec 2005, 11574 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 #include <stdlib.h>
   17 #include <stdio.h>
   18 #include <string.h>
   19 #include <unistd.h>
   20 #include <fnmatch.h>
   21 #include <errno.h>
   22 #include <dlfcn.h>
   23 #include <libgen.h>
   24 #include <dirent.h>
   25 
   26 #include <libxml/parser.h>
   27 #include <libxml/tree.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 FALSE 0
   36 #define TRUE 1
   37 
   38 #define XML_VERSION "1.1"
   39 
   40 typedef struct {
   41     char *path;
   42     xmlDocPtr doc;
   43     int writable;
   44     int modified;
   45     xmlNodePtr current;
   46 } xmlfileContext;
   47 
   48 void rewinddb(xmlfileContext *con);
   49 
   50 char * base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
   51 
   52 /**
   53  * returns data encoded in base64 (in a newly allocated buffer).
   54  */
   55 char * base64_encode(char *in, unsigned long len)
   56 {
   57     char b[3];
   58     int i = 0, j, r;
   59     char *out, *p;
   60 
   61     p = out = (char *) malloc(len * 4 / 3 + 5);
   62 
   63     while(i < len) {
   64         r = len - i;
   65         b[0] = 0; b[1] = 0; b[2] = 0;
   66         for(j=0; j<r && j<3; j++,i++)
   67             b[j] = *in++;
   68         *p++ = base64_chars[(b[0] & 252) >> 2];
   69         *p++ = base64_chars[((b[0] & 3) << 4) | ((b[1] & 240) >> 4)];
   70 
   71         if(r < 2) *p++ = '='; else
   72             *p++ = base64_chars[((b[1] & 15) << 2) | ((b[2] & 192) >> 6)];
   73         if(r < 3) *p++ = '='; else
   74             *p++ = base64_chars[b[2] & 63];
   75     }
   76     *p++ = 0;
   77 
   78     return out;
   79 }
   80 
   81 /**
   82  * return index of character in the base64 encoding table.
   83  * this depends on ASCII ordering..
   84  */
   85 inline char base64_lookup(char in)
   86 {
   87     if(in < '0') return in == '+' ? 62 : 63;
   88     if(in < 'A') return in - '0' + 52;
   89     if(in < 'a') return in - 'A';
   90     return in - 'a' + 26;
   91 }
   92 
   93 /**
   94  * returns data decoded from base64 (in a newly allocated buffer).
   95  * writes data length into int len.
   96  */
   97 void * base64_decode(const char *in, unsigned long *len)
   98 {
   99     char *out, *p, c;
  100 
  101     p = out = (char *) malloc(strlen(in) * 3 / 4 + 5);
  102     *len = 0;
  103 
  104     for(;;) {
  105         if(!*in) return out;
  106         *p = (base64_lookup(*in) << 2); in++;
  107         *p = *p | (((c = base64_lookup(*in++)) & 48) >> 4);
  108         p ++;
  109         *len = *len + 1;
  110         if(*in == '=') return out;
  111         *p = ((c & 15) << 4);
  112         *p = *p | (((c = base64_lookup(*in++)) & 60) >> 2);
  113         p ++;
  114         *len = *len + 1;
  115         if(*in == '=') return out;
  116         *p++ = ((c & 3) << 6) | base64_lookup(*in++);
  117         *len = *len + 1;
  118     }
  119 }
  120 
  121 
  122 ///////////////////////////////////////////////////////////////////////////////
  123 //                                                                           //
  124 // A P I   F U N C T I O N S                                                 //
  125 //                                                                           //
  126 ///////////////////////////////////////////////////////////////////////////////
  127 void *opendb(char *path)
  128 {
  129     FILE *fp;
  130     int exists;
  131     xmlNodePtr cur;
  132     xmlChar *ver;
  133 
  134     LIBXML_TEST_VERSION
  135 
  136     xmlfileContext *con = (xmlfileContext *) malloc(sizeof(xmlfileContext));
  137     if(!con) return NULL;
  138 
  139     fp = fopen(path, "r+");
  140     exists = FALSE;
  141     con->writable = TRUE;
  142     if(!fp && errno == EACCES) {
  143         con->writable = FALSE;
  144         exists = TRUE;
  145     }
  146     if(fp) {
  147         exists = TRUE;
  148         fclose(fp);
  149     }
  150 
  151     con->doc = xmlReadFile(path, NULL, 0);
  152     if(!con->doc) {
  153         if(exists) {
  154             free(con);
  155             return NULL;
  156         } else {
  157             // creating new db
  158             fp = fopen(path, "w");
  159             if(!fp) {
  160                 perror("can't open or create DB");
  161                 free(con);
  162                 xmlCleanupParser();
  163                 return NULL;
  164             }
  165             fprintf(fp,"<?xml version=\"1.0\"?>\n");
  166             fprintf(fp,"<unipkg ver=\"" XML_VERSION "\">\n");
  167             fprintf(fp,"</unipkg>");
  168             fclose(fp);
  169 
  170             con->doc = xmlReadFile(path, NULL, 0);
  171             if(!con->doc) {
  172                 free(con);
  173                 xmlCleanupParser();
  174                 return NULL;
  175             }
  176         }
  177     }
  178 
  179     cur = xmlDocGetRootElement(con->doc);
  180     if(xmlStrcmp(cur->name, (const xmlChar *) "unipkg")) {
  181         xmlFreeDoc(con->doc);
  182         free(con);
  183         xmlCleanupParser();
  184         return NULL;
  185     }
  186 
  187     ver = xmlGetProp(cur, (const xmlChar *) "ver");
  188     if(!ver) {
  189         xmlFreeDoc(con->doc);
  190         free(con);
  191         xmlCleanupParser();
  192         return NULL;
  193     }
  194     if(xmlStrcmp(ver, (const xmlChar *) XML_VERSION)) {
  195         con->writable = FALSE;
  196     }
  197     xmlFree(ver);
  198 
  199     con->path = strdup(path);
  200     if(!con->path) {
  201         xmlFreeDoc(con->doc);
  202         free(con);
  203         xmlCleanupParser();
  204         return NULL;
  205     }
  206     rewinddb(con);
  207     con->modified = FALSE;
  208 
  209     return con;
  210 }
  211 
  212 void rewinddb(xmlfileContext *con)
  213 {
  214     con->current = xmlDocGetRootElement(con->doc);
  215     con->current = con->current->children;
  216     for(; con->current; con->current = con->current->next)
  217         if(con->current->type == XML_ELEMENT_NODE &&
  218                 !xmlStrcmp(con->current->name, (const xmlChar *) "package"))
  219                     break;
  220 }
  221 
  222 int iswriteable(xmlfileContext *con)
  223 {
  224     return con->writable;
  225 }
  226 
  227 int syncdb(xmlfileContext *handle)
  228 {
  229     if(handle->writable && handle->modified)
  230         xmlSaveFormatFile(handle->path, handle->doc, 1);
  231     return 0;
  232 }
  233 
  234 int closedb(xmlfileContext *handle)
  235 {
  236     if(handle->writable && handle->modified)
  237         xmlSaveFormatFile(handle->path, handle->doc, 1);
  238 
  239     xmlFreeDoc(handle->doc);
  240     free(handle->path);
  241     xmlCleanupParser();
  242     free(handle);
  243 
  244     return 0;
  245 }
  246 
  247 #define GETPROP(x) \
  248     buf = xmlGetProp(con->current, (const xmlChar *) #x); \
  249     if(buf) { \
  250         pinfo->x = strdup((char *)buf); \
  251         if(!pinfo->x) return 1; \
  252         xmlFree(buf); \
  253     } else pinfo->x = strdup("");
  254 
  255 #define GETLONG(x) \
  256     buf = xmlGetProp(con->current, (const xmlChar *) #x); \
  257     if(buf) { \
  258         pinfo->x = atol((char *)buf); \
  259         xmlFree(buf); \
  260     } else pinfo->x = 0;
  261 
  262 #define GETEL(x) \
  263     if(!xmlStrcmp(cur->name, (const xmlChar *)#x)) { \
  264         buf = xmlNodeListGetString(con->doc, cur->children, 1); \
  265         if(buf) { \
  266             pinfo->x = strdup((char *) buf); \
  267             if(!pinfo->x) return 1; \
  268             xmlFree(buf); \
  269         } \
  270         continue; \
  271     }
  272 
  273 #define GETSCR(x) \
  274     if(!xmlStrcmp(cur->name, (const xmlChar *) #x)) { \
  275         buf = xmlNodeListGetString(con->doc, cur->children, 1); \
  276         if(buf) { \
  277             pinfo->x.data = base64_decode((char *)buf, &pinfo->x.len); \
  278             xmlFree(buf); \
  279         } \
  280         for(i=0; i<A_COUNT; i++) { \
  281             sprintf((char *) sbuf, "parm%x", i); \
  282             buf = xmlGetProp(cur, (xmlChar *) sbuf); \
  283             if(buf) { \
  284                 pinfo->x.parameters[i] = strdup((char *) buf); \
  285                 xmlFree(buf); \
  286             } \
  287         } \
  288         continue; \
  289     }
  290 
  291 int readpkg(xmlfileContext *con, pkginfo *pinfo)
  292 {
  293     xmlChar *buf;
  294     xmlNodePtr cur;
  295     char sbuf[32];
  296     int i;
  297     int filecnt = 0;
  298 
  299     if(!con->current) return 1;
  300 
  301     clearpinfo(pinfo);
  302 
  303     GETPROP(name)
  304     GETPROP(version)
  305     GETLONG(pkgsize)
  306 
  307     buf = xmlGetProp(con->current, (const xmlChar *) "filecount");
  308     if(!buf) return 1;
  309     pinfo->filecount = atoi((char *) buf);
  310     xmlFree(buf);
  311     if(pinfo->filecount)
  312         pinfo->files = malloc(sizeof(fileinfo) * pinfo->filecount);
  313     filecnt = 0;
  314 
  315     for(cur = con->current->children; cur; cur = cur->next) {
  316         if(cur->type == XML_ELEMENT_NODE) {
  317 
  318             if(!xmlStrcmp(cur->name, (const xmlChar *) "file") && filecnt < pinfo->filecount) {
  319                 buf = xmlGetProp(cur, (const xmlChar *) "name");
  320                 if(!buf) continue;
  321                 pinfo->files[filecnt].name = (char*)buf;
  322                 pinfo->files[filecnt++].flag = F_IRRELEVANT;
  323                 continue;
  324             }
  325 
  326             GETEL(description)
  327             GETSCR(preinst)
  328             GETSCR(postinst)
  329             GETSCR(prerm)
  330             GETSCR(postrm)
  331         }
  332     }
  333 
  334     for(con->current = con->current->next; con->current != NULL; con->current = con->current->next)
  335         if(con->current->type == XML_ELEMENT_NODE &&
  336                 !xmlStrcmp(con->current->name, (const xmlChar *) "package"))
  337                     break;
  338 
  339     return 0;
  340 }
  341 
  342 #define WRITETEXT(x) \
  343     if(pinfo->x) { \
  344         cd = xmlNewNode(NULL, (const xmlChar *) #x); \
  345         xmlAddChild(cd, xmlNewCDataBlock(con->doc, (const xmlChar *) pinfo->x, strlen(pinfo->x))); \
  346         xmlAddChild(new, cd); \
  347     }
  348 
  349 #define WRITESCR(x) \
  350     if(pinfo->x.data) { \
  351         cd = xmlNewNode(NULL, (const xmlChar *) #x); \
  352         buf64 = base64_encode(pinfo->x.data, pinfo->x.len); \
  353         xmlAddChild(cd, xmlNewText((xmlChar *) buf64)); \
  354         free(buf64); \
  355         for(i=0; i<A_COUNT; i++) { \
  356             if(pinfo->x.parameters[i]) { \
  357                 sprintf((char*)buf, "parm%x", i); \
  358                 xmlSetProp(cd, (xmlChar *) buf, (xmlChar *) pinfo->x.parameters[i]); \
  359             } \
  360         } \
  361         xmlAddChild(new, cd); \
  362     } 
  363 
  364 
  365 int writepkg(xmlfileContext *con, pkginfo *pinfo)
  366 {
  367     xmlNodePtr cur, new, fil, cd;
  368     char buf[32], *buf64;
  369     int i;
  370 
  371     if(!pinfo) return 1;
  372     if(!pinfo->name) return 1;
  373     if(!strlen(pinfo->name)) return 1;
  374 
  375     con->modified = TRUE;
  376 
  377     cur = xmlDocGetRootElement(con->doc);
  378     new = xmlNewNode(NULL, (const xmlChar *) "package");
  379     xmlAddChild(cur, new);
  380     xmlNewProp(new, (const xmlChar *) "name", (xmlChar *) pinfo->name);
  381     xmlNewProp(new, (const xmlChar *) "version", (xmlChar *) pinfo->version);
  382     sprintf(buf, "%ld", pinfo->pkgsize);
  383     xmlNewProp(new, (const xmlChar *) "pkgsize", (xmlChar *) buf);
  384 
  385     WRITETEXT(description)
  386     WRITESCR(preinst)
  387     WRITESCR(postinst)
  388     WRITESCR(prerm)
  389     WRITESCR(postrm)
  390 
  391     sprintf(buf, "%ld", pinfo->filecount);
  392     xmlNewProp(new, (const xmlChar *) "filecount", (xmlChar *)buf);
  393     for(i=0; i<pinfo->filecount; i++) {
  394         fil = xmlNewNode(NULL, (const xmlChar *) "file");
  395         xmlAddChild(new, fil);
  396         xmlNewProp(fil, (const xmlChar *) "name", (xmlChar *) pinfo->files[i].name);
  397     }
  398 
  399     return 0;
  400 }
  401 
  402 int delpkg(xmlfileContext *con, char *pneedle)
  403 {
  404     xmlNodePtr cur, del;
  405     xmlChar *name;
  406 
  407     con->modified = TRUE;
  408     cur = xmlDocGetRootElement(con->doc);
  409     cur = cur->children;
  410 
  411     while(cur) {
  412         if(!xmlStrcmp(cur->name, (const xmlChar *) "package")) {
  413             name = xmlGetProp(cur, (const xmlChar *) "name");
  414             if(name) {
  415                 if(!fnmatch(pneedle, (char*)name, 0)) {
  416                     xmlFree(name);
  417                     del = cur;
  418                     cur = cur->next;
  419                     xmlUnlinkNode(del);
  420                     xmlFreeNode(del);
  421                     continue;
  422                 }
  423                 xmlFree(name);
  424             }
  425         }
  426 
  427         cur = cur->next;
  428     }
  429 
  430     rewinddb(con);
  431 
  432     return 0;
  433 }
  434 
  435 
  436 int findpkg(xmlfileContext *con, pkginfo needle, pkginfo *reval, int matchtype)
  437 {
  438     pkginfo *tmppinfo;
  439     int found, i, j;
  440 
  441     if (reval) {
  442         tmppinfo = reval;
  443     } else {
  444         tmppinfo = (pkginfo *) malloc(sizeof(pkginfo));
  445         clearpinfo(tmppinfo);
  446     }
  447 
  448     while (!readpkg(con, tmppinfo)) {
  449         if (matchtype & MATCH_NAME) {
  450             if (fnmatch(needle.name, tmppinfo->name, 0)) {
  451                 freepinfo(tmppinfo);
  452                 continue;
  453             }
  454         }
  455 
  456         if ((needle.filecount > 0) && (matchtype & MATCH_FILE)) {
  457             found = 0;
  458             for(i = 0; i < needle.filecount; i++) {
  459                 for(j = 0; j < tmppinfo->filecount; j++) {
  460                     // We do NOT want to match directories.
  461                     
  462                     // FIXME FIXME, this fucks up when using unipkg findfile bzlib
  463                     if (needle.files[i].flag == F_DIRECTORY) continue;
  464                     if (!fnmatch(needle.files[i].name, tmppinfo->files[j].name,0)) {
  465                         found = 1;
  466                         i = needle.filecount;
  467                         break;
  468                     }
  469                 }
  470             }
  471             if (!found) {
  472                 freepinfo(tmppinfo);
  473                 clearpinfo(tmppinfo);
  474                 continue;
  475             }
  476         }
  477 
  478         if (!reval) {
  479             freepinfo(tmppinfo);
  480             free(tmppinfo);
  481         }
  482         return (matchtype & MATCH_OVRWR) ? -1 : 1;
  483     }
  484 
  485     if(!reval) {
  486         free(tmppinfo);
  487     }
  488     return 0;
  489 }