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