"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 }