Annotation of rpm2html/rpmopen.c, revision 1.95
1.1 veillard 1: /*
2: * rpmopen.c : open an extract informations from RPM files.
3: *
1.50 veillard 4: * See Copyright for the status of this software.
1.1 veillard 5: *
1.95 ! daniel 6: * $Id: rpmopen.c,v 1.94 2000/12/18 11:29:55 daniel Exp $
1.1 veillard 7: */
8:
1.9 veillard 9: #include <config.h>
1.1 veillard 10: #include <sys/types.h>
11: #include <sys/stat.h>
1.9 veillard 12: #ifdef HAVE_FCNTL_H
1.1 veillard 13: #include <fcntl.h>
1.9 veillard 14: #endif
1.1 veillard 15: #include <stdio.h>
16: #include <stdlib.h>
17: #include <string.h>
1.9 veillard 18: #ifdef HAVE_UNISTD_H
1.1 veillard 19: #include <unistd.h>
1.9 veillard 20: #endif
1.6 veillard 21: #include <dirent.h>
1.13 veillard 22: #include <errno.h>
1.31 veillard 23: #include <time.h>
1.1 veillard 24:
25: #include <rpm/rpmlib.h>
1.70 daniel 26: #include <rpm/rpmmacro.h> /* Added by A. Gibert */
1.83 veillard 27: //#include <rpm/rpmlead.h> - not included in rpm-devel package
28: // XXX hack - I hope that readLead IS in librpm.o even when .h is missing
29: int readLead(FD_t fd, /*@out@*/struct rpmlead *lead);
30: //#include <rpm/signature.h> - not included in rpm-devel package
31: // XXX hack - I hope that int rpmReadSignature IS in librpm.o even when .h is missing
32: int rpmReadSignature(FD_t fd, /*@out@*/ Header *header, short sig_type);
1.1 veillard 33:
1.86 veillard 34: #if defined(WITH_GPG)
35: #include <sys/wait.h>
36: #endif
37:
1.77 veillard 38: #include "rpm2html.h"
1.1 veillard 39: #include "rpmdata.h"
1.7 veillard 40: #include "html.h"
1.40 httpng 41: #include "rdf.h"
1.12 veillard 42: #include "language.h"
1.75 veillard 43: #ifdef WITH_SQL
44: #include "sql.h"
45: #endif
1.1 veillard 46:
1.66 daniel 47: #ifndef HAVE_SNPRINTF
48: #error You really need snprintf ...
49: #endif
1.1 veillard 50: /*
1.69 daniel 51: * Get the internal number associated with an RPM tag.
1.1 veillard 52: */
53: static int getTagNumber(char *tag) {
54: int i;
55: const struct headerTagTableEntry * t;
56:
57: for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
58: if (!strcasecmp(tag, t->name)) return(t->val);
59: }
60: fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
61: return(-1);
62: }
63:
64: /*
1.58 daniel 65: * Free up the extra data not needed for the last stage processing.
66: */
67:
68: void rpmFreeExtraData(rpmDataPtr rpm) {
69: rpmExtraDataPtr extra;
1.83 veillard 70: int n1;
1.58 daniel 71:
72: if ((rpm == NULL) || (rpm->extra == NULL)) return;
73: extra = rpm->extra;
1.93 veillard 74: if (extra->packager != NULL) xmlFree(extra->packager);
75: if (extra->description != NULL) xmlFree(extra->description);
76: if (extra->copyright != NULL) xmlFree(extra->copyright);
77: if (extra->changelog != NULL) xmlFree(extra->changelog);
78: if (extra->srcrpm != NULL) xmlFree(extra->srcrpm);
79: if (extra->host != NULL) xmlFree(extra->host);
80: if (extra->resources != NULL) xmlFree(extra->resources);
81: if (extra->requires != NULL) xmlFree(extra->requires);
82: if (extra->filelist != NULL) xmlFree(extra->filelist);
1.83 veillard 83: if (extra->sigs != NULL) {
1.84 daniel 84: for (n1 = 0; n1 < extra->nb_sigs; n1++)
1.86 veillard 85: if (extra->sigs[n1] != NULL) {
86: if (extra->sigs[n1]->sig != NULL)
1.93 veillard 87: xmlFree(extra->sigs[n1]->sig);
1.86 veillard 88: #if defined(WITH_GPG)
89: if (extra->sigs[n1]->resolve != NULL)
1.93 veillard 90: xmlFree(extra->sigs[n1]->resolve);
1.86 veillard 91: #endif
1.93 veillard 92: xmlFree(extra->sigs[n1]);
1.86 veillard 93: }
1.93 veillard 94: xmlFree(extra->sigs);
1.83 veillard 95: }
1.93 veillard 96: xmlFree(extra);
1.58 daniel 97: }
98:
99: /*
1.59 daniel 100: * check a dependancy name to get rid of bad deps due to bad scripts
1.55 daniel 101: * or spec files.
1.53 veillard 102: */
103: int checkResourceName(const char *res) {
1.59 daniel 104: int isname = 0;
105: const char *base = res;
1.55 daniel 106:
1.53 veillard 107: if (*res == 0) return(0);
1.55 daniel 108:
109: /*
1.59 daniel 110: * we only accept absolute pathnames.
1.55 daniel 111: */
1.59 daniel 112: if (*res == '/') isname = 1;
1.53 veillard 113: while (*res != 0) {
1.59 daniel 114: if (((*res >= 'A') && (*res <= 'Z')) ||
115: ((*res >= 'a') && (*res <= 'z')) ||
1.53 veillard 116: ((*res >= '0') && (*res <= '9')) ||
1.55 daniel 117: (*res == '-') || (*res == '.') ||
118: (*res == '@') || (*res == '_') ||
1.59 daniel 119: (*res == '+') ||
120: ((*res == '/') && (isname == 1)))
1.53 veillard 121: res++;
122: else
123: return(0);
1.59 daniel 124: if ((res - base) > 100) return(0);
125: }
126: return(1);
127: }
128:
129: /*
130: * check a release name
131: */
132: int checkReleaseName(const char *res) {
133: const char *base = res;
134:
135: if (*res == 0) return(0);
136:
137: while (*res != 0) {
138: if (((*res >= 'A') && (*res <= 'Z')) ||
139: ((*res >= 'a') && (*res <= 'z')) ||
140: ((*res >= '0') && (*res <= '9')) ||
141: (*res == '-') || (*res == '.') ||
142: (*res == '@') || (*res == '_') ||
143: (*res == '+'))
144: res++;
145: else
146: return(0);
147: if ((res - base) > 20) return(0);
148: }
149: return(1);
150: }
151:
152: /*
153: * check a group name
154: */
155: int checkGroupName(const char *res) {
156: const char *base = res;
157:
158: /* Grrr !!! Suse packages have an empty Group name
159: if (*res == 0) return(0);
160: */
161:
162: while (*res != 0) {
163: if (((*res >= 'A') && (*res <= 'Z')) ||
164: ((*res >= 'a') && (*res <= 'z')) ||
165: ((*res >= '0') && (*res <= '9')) ||
166: (*res == ' ') || (*res == '.') ||
167: (*res == '+') || (*res == '/') ||
168: (*res == '-'))
169: res++;
170: else
171: return(0);
172: if ((res - base) > 60) return(0);
173: }
174: return(1);
175: }
176:
177: /*
178: * check a version name
179: */
180: int checkVersionName(const char *res) {
181: const char *base = res;
182:
183: if (*res == 0) return(0);
184:
185: while (*res != 0) {
186: if (((*res >= 'A') && (*res <= 'Z')) ||
187: ((*res >= 'a') && (*res <= 'z')) ||
188: ((*res >= '0') && (*res <= '9')) ||
189: (*res == '-') || (*res == '.') ||
190: (*res == '@') || (*res == '_') ||
191: (*res == '+'))
192: res++;
193: else
194: return(0);
195: if ((res - base) > 20) return(0);
1.53 veillard 196: }
197: return(1);
198: }
1.60 daniel 199:
1.86 veillard 200: #if defined(WITH_GPG)
201: /*
202: * rpmResolveGPGPSignatures : resolve GPG and PGP signatures found in package
203: * code based on rpm-4.0-0.45
204: */
205: void rpmResolveGPGPSignature(const char *nameRpm, const char *sigtarget,
206: const char *sigfile, rpmDataPtr rpm, int sign) {
207: int pid, status, outpipe[2];
208: FILE *file;
209: int rsize = 128, crsize;
210: unsigned char buf[8192];
211:
212: /* Now run GPG */
213: outpipe[0] = outpipe[1] = 0;
214: pipe(outpipe);
215:
216: if (!(pid = fork())) {
217: close(outpipe[0]);
218: /* gpg version 0.9 sends its output to stderr. */
219: dup2(outpipe[1], STDERR_FILENO);
220:
221: execlp(GPG_PROG, GPG_PROG,
222: "--batch", "--no-verbose",
223: "--verify", sigfile, sigtarget,
224: NULL);
225: fprintf(stderr, "%s exec failed!\n", GPG_PROG);
226: exit(1);
227: }
228:
229: close(outpipe[1]);
230: file = fdopen(outpipe[0], "r");
1.93 veillard 231: rpm->extra->sigs[sign]->resolve = xmlMalloc(sizeof(char) * rsize);
1.86 veillard 232: rpm->extra->sigs[sign]->resolve[0] = '\0';
233: while (fgets(buf, 1024, file)) {
234: crsize = strlen(buf) + strlen(rpm->extra->sigs[sign]->resolve);
235: if (crsize >= rsize) {
236: rsize = crsize * 2;
1.93 veillard 237: rpm->extra->sigs[sign]->resolve = xmlRealloc(rpm->extra->sigs[sign]->resolve,
1.86 veillard 238: sizeof(char) * rsize);
239: if (rpm->extra->sigs[sign]->resolve == NULL) {
240: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
241: rsize, strerror(errno));
242: exit (1);
243: }
244: }
245:
246: strcat(rpm->extra->sigs[sign]->resolve, buf);
247: }
248: fclose(file);
249:
250: (void)waitpid(pid, &status, 0);
251: }
252:
253: /*
254: * rpmResolveMD5Signatures : resolve MD5 signatures found in package
255: * code based on rpm-4.0-0.45
256: * for now, we are not checking whether MD5 sums are OK
257: */
258: /*void rpmResolveMD5Signature(const char *nameRpm, const char *sigtarget,
259: const char *sigfile, rpmDataPtr rpm, int sign) {
260: }*/
261:
262: /*
263: * rpmResolveSignatures : resolve signatures found in package
264: * code based on rpm-4.0-0.45
265: */
266: void rpmResolveSignatures(const char *path, const char *nameRpm,
267: const char *sigtarget, rpmDataPtr rpm) {
268: int sign = 0;
269:
270: if (rpm == NULL || rpm->extra->nb_sigs == 0 || sigtarget == NULL) return;
271:
272: for (sign = 0; sign < rpm->extra->nb_sigs; sign++) {
273: FD_t sfd;
274: char *sigfile = NULL;
275:
276: if (rpm->extra->sigs[sign]->tag != RPMSIGTAG_PGP
277: && rpm->extra->sigs[sign]->tag != RPMSIGTAG_GPG)
278: continue;
279:
280: /* Write out the signature */
1.93 veillard 281: sigfile = xmlMalloc(30);
1.86 veillard 282: strcpy(sigfile, "/tmp/rpm2html.sig.XXXXXX");
283: sigfile = mktemp(sigfile);
284: sfd = Fopen(sigfile, "w.fdio");
285: (void)Fwrite(rpm->extra->sigs[sign]->sig, sizeof(char),
286: rpm->extra->sigs[sign]->size, sfd);
287: Fclose(sfd);
288:
289: switch(rpm->extra->sigs[sign]->tag) {
290: case RPMSIGTAG_PGP:
291: case RPMSIGTAG_GPG:
292: rpmResolveGPGPSignature(nameRpm, sigtarget, sigfile, rpm, sign);
293: break;
294: /*case RPMSIGTAG_MD5:
295: rpmResolveMD5Signature(nameRpm, sigtarget, sigfile, rpm, sign);
296: break;*/
297: default:
298: break;
299: }
300:
301: if (sigfile != NULL) {
302: unlink(sigfile);
1.93 veillard 303: xmlFree(sigfile);
1.86 veillard 304: }
305: }
306: }
307: #endif
308:
1.53 veillard 309: /*
1.11 veillard 310: * rpmAnalyze : analyze an RPM record, read and parse the header and
311: * fill the informations in the database.
1.1 veillard 312: */
1.62 daniel 313: #define ENTRY_CLEANUP(p) \
314: if ((type == RPM_STRING_ARRAY_TYPE || type == RPM_I18NSTRING_TYPE)&&\
315: (p != NULL)) { free((p)); p = NULL; }
316:
1.60 daniel 317: static char *buffer = NULL;
318: static int buffer_size = 50 * 1024 * sizeof(char);
1.61 daniel 319:
1.86 veillard 320: rpmDataPtr rpmAnalyze(char *path, char *nameRpm, const char *sigtarget,
321: Header h, Header s, rpmDirPtr dir, rpmSubdirPtr tree,
322: time_t stamp, int isSource) {
1.11 veillard 323: int installed = dir->installbase;
1.2 veillard 324: char * name = NULL, * version = NULL, * release = NULL;
1.1 veillard 325: int_32 count, type;
1.2 veillard 326: void * p = NULL;
1.10 veillard 327: int val, i, j;
1.1 veillard 328: rpmDataPtr rpm = NULL;
1.11 veillard 329: static char nameBuffer[500];
1.75 veillard 330: #ifdef WITH_SQL
331: int id;
332: #endif
1.83 veillard 333: HeaderIterator sIter;
1.1 veillard 334:
1.41 veillard 335: if (buffer == NULL) {
1.93 veillard 336: buffer = (char *) xmlMalloc(buffer_size);
1.41 veillard 337: if (buffer == NULL) {
338: fprintf(stderr, "cannot allocate %d bytes: %s\n", buffer_size,
339: strerror(errno));
340: exit(1);
341: }
342: }
343:
1.1 veillard 344: /* extract informations from the header */
345: headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
1.49 veillard 346: if (name == NULL) {
347: fprintf(stderr, "Invalid package %s : no name\n", nameRpm);
348: return(NULL);
349: }
350: if (!(((name[0] >= 'a') && (name[0] <= 'z')) ||
351: ((name[0] >= 'A') && (name[0] <= 'Z')) ||
352: ((name[0] >= '0') && (name[0] <= '9')))) {
353: fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
1.62 daniel 354: ENTRY_CLEANUP(name)
1.49 veillard 355: return(NULL);
356: }
1.59 daniel 357: if (!checkResourceName(name)) {
358: fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
1.62 daniel 359: ENTRY_CLEANUP(name)
1.59 daniel 360: return(NULL);
361: }
1.1 veillard 362: headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
1.49 veillard 363: if ((version == NULL) || (version[0] == 0)) {
364: fprintf(stderr, "Invalid package %s : version invalid\n", nameRpm);
1.62 daniel 365: ENTRY_CLEANUP(name)
366: ENTRY_CLEANUP(version)
1.49 veillard 367: return(NULL);
368: }
1.59 daniel 369: if (!checkVersionName(version)) {
370: fprintf(stderr, "Invalid package %s : garbled version\n", nameRpm);
1.62 daniel 371: ENTRY_CLEANUP(name)
372: ENTRY_CLEANUP(version)
1.59 daniel 373: return(NULL);
374: }
1.1 veillard 375: headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
1.49 veillard 376: if ((release == NULL) || (release[0] == 0)) {
377: fprintf(stderr, "Invalid package %s : release invalid\n", nameRpm);
1.62 daniel 378: ENTRY_CLEANUP(name)
379: ENTRY_CLEANUP(version)
380: ENTRY_CLEANUP(release)
1.49 veillard 381: return(NULL);
382: }
1.59 daniel 383: if (!checkReleaseName(release)) {
384: fprintf(stderr, "Invalid package %s : garbled release\n", nameRpm);
1.62 daniel 385: ENTRY_CLEANUP(name)
386: ENTRY_CLEANUP(version)
387: ENTRY_CLEANUP(release)
1.59 daniel 388: return(NULL);
389: }
1.1 veillard 390:
1.58 daniel 391: /* allocate a new rpmData block, and an rpmExtraData block fill them */
1.93 veillard 392: rpm = (rpmDataPtr) xmlMalloc(sizeof(rpmData));
1.1 veillard 393: if (rpm == NULL) {
1.41 veillard 394: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
395: strerror(errno));
396: return(NULL);
1.1 veillard 397: }
1.44 veillard 398: memset(rpm, 0, sizeof(rpmData));
1.93 veillard 399: rpm->extra = (rpmExtraDataPtr) xmlMalloc(sizeof(rpmExtraData));
1.58 daniel 400: if (rpm == NULL) {
401: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmExtraData),
402: strerror(errno));
403: return(NULL);
404: }
405: memset(rpm->extra, 0, sizeof(rpmExtraData));
1.6 veillard 406: rpm->dir = dir;
1.36 veillard 407: if (tree) {
408: if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
1.61 daniel 409: rpm->subdir = stringAdd(tree->rpmpath);
1.36 veillard 410: else
411: rpm->subdir = NULL;
412: } else
413: rpm->subdir = NULL;
1.58 daniel 414: rpm->extra->stamp = stamp;
1.61 daniel 415: rpm->name = stringAdd(name);
1.62 daniel 416: ENTRY_CLEANUP(name)
1.61 daniel 417: rpm->version = stringAdd(version);
1.62 daniel 418: ENTRY_CLEANUP(version)
1.61 daniel 419: rpm->release = stringAdd(release);
1.62 daniel 420: ENTRY_CLEANUP(release)
1.1 veillard 421:
1.26 veillard 422: /* get all the resources provided by this RPM */
1.2 veillard 423: if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.93 veillard 424: rpm->summary = xmlStrdup(localizedStrings[LANG_NO_SUMMARY]);
1.2 veillard 425: } else {
1.93 veillard 426: rpm->summary = xmlStrdup((char *) p);
1.2 veillard 427: }
1.62 daniel 428: ENTRY_CLEANUP(p);
1.28 veillard 429: if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p ||
430: (type != RPM_STRING_TYPE)) {
1.93 veillard 431: rpm->extra->description = xmlStrdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.2 veillard 432: } else {
1.93 veillard 433: rpm->extra->description = xmlStrdup((char *) p);
1.2 veillard 434: }
1.62 daniel 435: ENTRY_CLEANUP(p);
1.28 veillard 436: if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p ||
437: (type != RPM_STRING_TYPE)) {
1.61 daniel 438: rpm->distribution = stringAdd(localizedStrings[LANG_UNKNOWN]);
1.2 veillard 439: } else {
1.61 daniel 440: rpm->distribution = stringAdd((char *) p);
1.2 veillard 441: }
1.62 daniel 442: ENTRY_CLEANUP(p);
1.52 daniel 443: if (isSource) {
1.61 daniel 444: rpm->arch = stringAdd("src");
1.11 veillard 445: if (nameRpm == NULL) {
1.66 daniel 446: snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.src.rpm",
1.52 daniel 447: name, version, release);
1.11 veillard 448: nameRpm = nameBuffer;
449: }
1.2 veillard 450: } else {
1.52 daniel 451: if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p ||
452: (type != RPM_STRING_TYPE)) {
453: if (type == RPM_INT8_TYPE) {
454: /*
455: * Old packages.
456: */
457: switch (*((char *) p)) {
458: case 1:
1.61 daniel 459: rpm->arch = stringAdd("i386");
1.52 daniel 460: break;
461: default:
1.61 daniel 462: rpm->arch = stringAdd("src");
1.52 daniel 463: break;
464: }
465: } else
1.61 daniel 466: rpm->arch = stringAdd(localizedStrings[LANG_NONE]);
1.52 daniel 467: if (nameRpm == NULL) {
1.66 daniel 468: snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.rpm", name, version, release);
1.52 daniel 469: nameRpm = nameBuffer;
470: }
471: } else {
1.61 daniel 472: rpm->arch = stringAdd((char *) p);
1.52 daniel 473: if (nameRpm == NULL) {
1.66 daniel 474: snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.%s.rpm",
1.52 daniel 475: name, version, release, (char *)p);
476: nameRpm = nameBuffer;
477: }
1.11 veillard 478: }
1.62 daniel 479: ENTRY_CLEANUP(p);
1.2 veillard 480: }
1.28 veillard 481: if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p ||
482: (type != RPM_STRING_TYPE)) {
1.29 veillard 483: if (type == RPM_INT8_TYPE) {
484: /*
1.32 veillard 485: * Old packages.
1.29 veillard 486: */
487: switch (*((char *) p)) {
488: case 1:
1.61 daniel 489: rpm->os = stringAdd("linux");
1.29 veillard 490: break;
491: default:
1.61 daniel 492: rpm->os = stringAdd("linux");
1.29 veillard 493: break;
494: }
495: } else
1.61 daniel 496: rpm->os = stringAdd("");
1.7 veillard 497: } else {
1.61 daniel 498: rpm->os = stringAdd((char *) p);
1.7 veillard 499: }
1.62 daniel 500: ENTRY_CLEANUP(p);
1.28 veillard 501: if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p ||
502: (type != RPM_STRING_TYPE)) {
1.7 veillard 503: rpm->vendor = NULL;
1.2 veillard 504: } else {
1.61 daniel 505: rpm->vendor = stringAdd((char *) p);
1.2 veillard 506: }
1.62 daniel 507: ENTRY_CLEANUP(p);
1.28 veillard 508: if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p ||
509: (type != RPM_STRING_TYPE)) {
1.61 daniel 510: rpm->group = stringAdd(localizedStrings[LANG_NO_GROUP]);
1.2 veillard 511: } else {
1.61 daniel 512: rpm->group = stringAdd((char *) p);
1.59 daniel 513: }
1.62 daniel 514: ENTRY_CLEANUP(p);
1.59 daniel 515: if (!checkGroupName(rpm->group)) {
516: fprintf(stderr, "Invalid package %s : garbled group\n", nameRpm);
1.74 daniel 517: if (rpm->name)
518: stringFree(rpm->name);
519: if (rpm->version)
520: stringFree(rpm->version);
521: if (rpm->release)
522: stringFree(rpm->release);
523: if (rpm->summary)
1.93 veillard 524: xmlFree(rpm->summary);
1.74 daniel 525: if (rpm->distribution)
526: stringFree(rpm->distribution);
527: if (rpm->arch)
528: stringFree(rpm->arch);
529: if (rpm->os)
530: stringFree(rpm->os);
531: if (rpm->vendor != NULL)
532: stringFree(rpm->vendor);
533: if (rpm->group != NULL)
534: stringFree(rpm->group);
1.93 veillard 535: xmlFree(rpm);
1.59 daniel 536: return(NULL);
1.2 veillard 537: }
1.28 veillard 538: if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p ||
539: (type != RPM_STRING_TYPE)) {
1.93 veillard 540: rpm->extra->host = xmlStrdup(localizedStrings[LANG_NO_HOST]);
1.2 veillard 541: } else {
1.93 veillard 542: rpm->extra->host = xmlStrdup((char *) p);
1.2 veillard 543: }
1.62 daniel 544: ENTRY_CLEANUP(p);
1.2 veillard 545: if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
546: rpm->size = 0;
547: } else {
548: rpm->size = *((int *) p);
549: }
1.62 daniel 550: ENTRY_CLEANUP(p);
1.11 veillard 551: if (installed) {
552: if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
553: rpm->date = 0;
554: } else {
555: rpm->date = *((int_32 *) p);
556: }
1.62 daniel 557: ENTRY_CLEANUP(p);
1.2 veillard 558: } else {
1.11 veillard 559: if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
560: rpm->date = 0;
561: } else {
562: rpm->date = *((int_32 *) p);
563: }
1.62 daniel 564: ENTRY_CLEANUP(p);
1.2 veillard 565: }
1.28 veillard 566: if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p ||
567: (type != RPM_STRING_TYPE)) {
1.93 veillard 568: rpm->extra->srcrpm = xmlStrdup("");
1.2 veillard 569: } else {
1.93 veillard 570: rpm->extra->srcrpm = xmlStrdup((char *) p);
1.2 veillard 571: }
1.62 daniel 572: ENTRY_CLEANUP(p);
1.28 veillard 573: if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p ||
574: (type != RPM_STRING_TYPE)) {
1.7 veillard 575: rpm->url = NULL;
576: } else {
1.93 veillard 577: rpm->url = xmlStrdup((char *) p);
1.7 veillard 578: }
1.62 daniel 579: ENTRY_CLEANUP(p);
1.28 veillard 580: if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p ||
581: (type != RPM_STRING_TYPE)) {
1.58 daniel 582: rpm->extra->packager = NULL;
1.7 veillard 583: } else {
1.93 veillard 584: rpm->extra->packager = xmlStrdup((char *) p);
1.7 veillard 585: }
1.62 daniel 586: ENTRY_CLEANUP(p);
1.28 veillard 587: if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p ||
588: (type != RPM_STRING_TYPE)) {
1.58 daniel 589: rpm->extra->copyright = NULL;
1.7 veillard 590: } else {
1.93 veillard 591: rpm->extra->copyright = xmlStrdup((char *) p);
1.7 veillard 592: }
1.62 daniel 593: ENTRY_CLEANUP(p);
1.31 veillard 594: /* Pick up changelog entries */
595: if (!headerGetEntry(h, RPMTAG_CHANGELOGTEXT, &type, &p, &count) || !p) {
1.58 daniel 596: rpm->extra->changelog = NULL;
1.31 veillard 597: } else {
598: time_t *dates;
599: char **names;
600: char **holdp = (char **)p;
601: char *cp;
602: struct tm *tm_buf;
603: int i, len, pos;
604: char date_string[50];
605: char *res = buffer;
1.42 veillard 606:
1.31 veillard 607: *res = '\0';
608: headerGetEntry(h, RPMTAG_CHANGELOGTIME, &type, (void *)&dates, &count);
609: headerGetEntry(h, RPMTAG_CHANGELOGNAME, &type, (void *)&names, &count);
610: for (i = 0; i < count; i++) {
1.42 veillard 611: if ((res - buffer) > (buffer_size - 1024)) {
612: int delta = res - buffer;
613:
1.41 veillard 614: buffer_size *= 2;
1.93 veillard 615: buffer = (char *) xmlRealloc(buffer, buffer_size);
1.42 veillard 616: if (buffer == NULL) {
617: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
618: buffer_size, strerror(errno));
619: exit(1);
620: }
621: res = &buffer[delta];
1.41 veillard 622: }
1.31 veillard 623: tm_buf = localtime(&dates[i]);
624: strftime(date_string, sizeof(date_string) - 1, "%a %b %d %Y", tm_buf);
1.66 daniel 625: len = snprintf(res, buffer_size, "* %s %s\n", date_string, names[i]);
1.31 veillard 626: res += len;
627: cp = holdp[i];
628: pos = 0;
629: while (*cp) {
630: if (pos++ == 0) {
631: *res++ = ' ';
632: *res++ = ' ';
633: }
634: *res++ = *cp;
635: if (*cp++ == '\n') pos = 0;
636: }
637: *res++ = '\n';
638: }
639: *res = '\0';
1.93 veillard 640: rpm->extra->changelog = xmlStrdup(buffer);
1.31 veillard 641: }
1.62 daniel 642: ENTRY_CLEANUP(p);
1.7 veillard 643: if (rpm->vendor == NULL) {
1.93 veillard 644: if (rpm->extra->packager != NULL) rpm->vendor = xmlStrdup(rpm->extra->packager);
645: else rpm->vendor = xmlStrdup(localizedStrings[LANG_UNKNOWN]);
1.7 veillard 646: }
1.2 veillard 647:
1.83 veillard 648: if (s == NULL)
649: rpm->extra->sigs = NULL;
650: else {
651: int tag, type;
652:
653: rpm->extra->max_sigs = 1;
1.93 veillard 654: rpm->extra->sigs = (rpmSigPtr *) xmlMalloc(sizeof(rpmSigPtr) *
1.83 veillard 655: rpm->extra->max_sigs);
656: rpm->extra->sigs[0] = NULL;
657: rpm->extra->nb_sigs = 0;
658:
659: for (sIter = headerInitIterator(s);
660: headerNextIterator(sIter, &tag, &type, &p, &count);
661: )
662: {
663: if ((tag != RPMSIGTAG_MD5) && (tag != RPMSIGTAG_PGP) && (tag != RPMSIGTAG_GPG))
664: continue;
665: if (rpm->extra->nb_sigs >= rpm->extra->max_sigs) {
666: rpm->extra->max_sigs *= 2;
1.93 veillard 667: rpm->extra->sigs = (rpmSigPtr *) xmlRealloc(rpm->extra->sigs,
1.83 veillard 668: sizeof(rpmSigPtr) * rpm->extra->max_sigs);
669: if (rpm->extra->sigs == NULL) {
670: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
671: rpm->extra->max_sigs, strerror(errno));
672: exit(1);
673: }
674: }
675:
1.93 veillard 676: rpm->extra->sigs[rpm->extra->nb_sigs] = (rpmSigPtr) xmlMalloc(sizeof(rpmSig));
1.83 veillard 677: rpm->extra->sigs[rpm->extra->nb_sigs]->tag = tag;
678: rpm->extra->sigs[rpm->extra->nb_sigs]->type = type;
679: rpm->extra->sigs[rpm->extra->nb_sigs]->size = count;
1.93 veillard 680: rpm->extra->sigs[rpm->extra->nb_sigs]->sig = xmlMalloc(count);
1.86 veillard 681: memcpy(rpm->extra->sigs[rpm->extra->nb_sigs]->sig, p, count);
682: #if defined(WITH_GPG)
683: rpm->extra->sigs[rpm->extra->nb_sigs]->resolve = NULL;
684: #endif
1.83 veillard 685: rpm->extra->nb_sigs++;
686: ENTRY_CLEANUP(p);
687: }
688: }
689:
1.93 veillard 690: rpm->filename = xmlStrdup(nameRpm);
1.11 veillard 691:
1.48 veillard 692: /* package-xxx.rpm provides at least the resource "package" */
1.1 veillard 693: val = getTagNumber("RPMTAG_PROVIDES");
694: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.58 daniel 695: rpm->extra->nb_resources = 1;
696: rpm->extra->max_resources = 1;
1.93 veillard 697: rpm->extra->resources = (rpmRessPtr *) xmlMalloc(sizeof(rpmRessPtr) *
1.58 daniel 698: rpm->extra->max_resources);
699: if (rpm->extra->resources == NULL) {
1.48 veillard 700: fprintf(stderr, ": ran out of memory\n");
701: exit(1);
702: }
1.58 daniel 703: rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
1.1 veillard 704: } else {
1.58 daniel 705: rpm->extra->max_resources = count + 1;
1.93 veillard 706: rpm->extra->resources = (rpmRessPtr *) xmlMalloc(sizeof(rpmRessPtr) *
1.58 daniel 707: rpm->extra->max_resources);
708: if (rpm->extra->resources == NULL) {
1.48 veillard 709: fprintf(stderr, ": ran out of memory\n");
710: exit(1);
1.1 veillard 711: }
1.58 daniel 712: rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
713: rpm->extra->nb_resources = 1;
1.1 veillard 714:
1.58 daniel 715: for (i = 0, j = rpm->extra->nb_resources; i < count;i++) {
1.53 veillard 716: if (!checkResourceName(((char **) p)[i])) continue;
1.92 veillard 717: if (!strcmp(((char **) p)[i],name)) continue;
1.58 daniel 718: rpm->extra->resources[j++] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4 veillard 719: }
1.58 daniel 720: rpm->extra->nb_resources = j;
1.4 veillard 721: }
1.62 daniel 722: ENTRY_CLEANUP(p);
1.4 veillard 723:
724: val = getTagNumber("RPMTAG_REQUIRENAME");
725: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.73 daniel 726: rpm->extra->nb_requires = 0;
1.58 daniel 727: rpm->extra->requires = NULL;
1.4 veillard 728: } else {
1.73 daniel 729: int_32 count2, count3, type2, type3;
730: void * q = NULL;
731: void * r = NULL;
732: int valv, valf;
1.4 veillard 733:
1.70 daniel 734: rpm->extra->max_requires = count;
1.93 veillard 735: rpm->extra->requires = (rpmRessPtr *) xmlMalloc(sizeof(rpmRessPtr) *
1.70 daniel 736: rpm->extra->max_requires);
737: if (rpm->extra->requires == NULL) {
738: fprintf(stderr, ": ran out of memory\n");
739: exit(1);
740: }
1.73 daniel 741: valv = getTagNumber("RPMTAG_REQUIREVERSION");
742: valf = getTagNumber("RPMTAG_REQUIREFLAGS");
743: headerGetEntry(h, valv, &type2, &q, &count2);
744: headerGetEntry(h, valf, &type3, &r, &count3);
1.70 daniel 745:
746: rpm->extra->nb_requires = 0;
747:
1.73 daniel 748: for (i = 0, j = 0; (i < count2) && (i < count3);i++) {
1.70 daniel 749: long anint = *(((long *)r)+i);
1.77 veillard 750: rpm_dep_flag flag = RPM2HTML_REQ_NONE;
1.70 daniel 751:
1.77 veillard 752: if ((anint & RPMSENSE_LESS) && (anint & RPMSENSE_EQUAL))
753: flag = RPM2HTML_REQ_LEQ;
754: else if (anint & RPMSENSE_LESS)
755: flag = RPM2HTML_REQ_LT;
756: if ((anint & RPMSENSE_GREATER) && (anint & RPMSENSE_EQUAL))
757: flag = RPM2HTML_REQ_GEQ;
758: else if (anint & RPMSENSE_GREATER)
759: flag = RPM2HTML_REQ_GT;
760: else if (anint & RPMSENSE_EQUAL)
761: flag = RPM2HTML_REQ_EQU;
1.53 veillard 762: if (!checkResourceName(((char **) p)[i])) continue;
1.70 daniel 763: rpm->extra->requires[j++] =
764: rpmRequAdd(((char **) p)[i],((char **) q)[i],
1.77 veillard 765: flag , rpm, installed);
1.1 veillard 766: }
1.58 daniel 767: rpm->extra->nb_requires = j;
1.73 daniel 768: if ((type2 == RPM_STRING_ARRAY_TYPE || type2 == RPM_I18NSTRING_TYPE)&&
769: (q != NULL)) { free((q)); q = NULL; }
770: if ((type3 == RPM_STRING_ARRAY_TYPE || type3 == RPM_I18NSTRING_TYPE)&&
771: (r != NULL)) { free((r)); r = NULL; }
772: for (;i < count;i++)
1.77 veillard 773: rpmRequAdd(((char **) p)[i], NULL, RPM2HTML_REQ_NONE,
774: rpm, installed);
1.5 veillard 775: }
1.62 daniel 776: ENTRY_CLEANUP(p);
1.69 daniel 777:
778: #if defined(RPMTAG_FILENAMES)
1.5 veillard 779: val = getTagNumber("RPMTAG_FILENAMES");
1.69 daniel 780: headerGetEntry(h, val, &type, &p, &count);
781: #else
782: rpmBuildFileList(h, (const char ***) &p, &count);
783: #endif
784:
785: if (count == 0) {
1.58 daniel 786: rpm->extra->filelist = NULL; /* No filelist in the package ! */
1.5 veillard 787: } else {
788: char *ptr = buffer;
1.42 veillard 789:
1.5 veillard 790: for (i = 0; i < count;i++) {
1.42 veillard 791: if ((ptr - buffer) > (buffer_size - 1024)) {
792: int delta = ptr - buffer;
793:
1.41 veillard 794: buffer_size *= 2;
1.93 veillard 795: buffer = (char *) xmlRealloc(buffer, buffer_size);
1.42 veillard 796: if (buffer == NULL) {
797: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
798: buffer_size, strerror(errno));
799: exit(1);
800: }
801: ptr = &buffer[delta];
1.41 veillard 802: }
1.66 daniel 803: ptr += snprintf(ptr, buffer_size, "%s\n", ((char **) p)[i]);
1.5 veillard 804: }
1.93 veillard 805: rpm->extra->filelist = xmlStrdup(buffer);
1.1 veillard 806: }
1.62 daniel 807: ENTRY_CLEANUP(p);
1.1 veillard 808:
1.86 veillard 809: #ifdef WITH_GPG
810: rpmResolveSignatures(path, nameRpm, sigtarget, rpm);
811: #endif WITH_GPG
812:
1.75 veillard 813: #ifdef WITH_SQL
814: id = sql_add_package(path, rpm->name, rpm->version, rpm->release,
815: rpm->arch, dir->no, rpm->url, rpm->extra->srcrpm,
816: dir->vendor, rpm->extra->packager,
817: rpm->group, rpm->summary, rpm->extra->description,
1.90 veillard 818: rpm->extra->copyright, rpm->date, rpm->size, rpm->os,
1.91 veillard 819: rpm->distribution, rpm->vendor);
1.76 veillard 820: if (id > 0) {
821: for (i = 0;i < rpm->extra->nb_resources;i++)
822: sql_add_provides(id, rpm->extra->resources[i]->name);
823: for (i = 0;i < rpm->extra->nb_requires;i++)
824: sql_add_requires(id, rpm->extra->requires[i]->name,
1.77 veillard 825: rpm->extra->requires[i]->flag,
1.76 veillard 826: rpm->extra->requires[i]->version);
827: }
1.75 veillard 828: #endif
829:
1.37 veillard 830: /* Add the package files to the real filesystem tree if asked for */
1.75 veillard 831: #ifdef WITH_SQL
832: if ((rpm->extra->filelist != NULL) &&
833: ((dir->build_tree != 0) || (id > 0))) {
834: #else
1.58 daniel 835: if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
1.75 veillard 836: #endif
1.37 veillard 837: char *cur, *filename;
838:
1.58 daniel 839: cur = rpm->extra->filelist;
1.37 veillard 840: while ((*cur != '\0') && (*cur != '/')) cur++;
841: filename = cur;
842: while (*cur != '\0') {
843: if ((*cur == '\n') || (*cur == '\r')) {
1.75 veillard 844: if (cur != filename) {
845: #ifdef WITH_SQL
846: if (dir->build_tree != 0)
847: rpmAddRealFile(dir->root, filename, rpm);
848: if (id > 0) {
849: *cur = 0;
850: sql_add_file(filename,id);
851: *cur = '\n';
852: }
853: #else
1.37 veillard 854: rpmAddRealFile(dir->root, filename, rpm);
1.75 veillard 855: #endif
856: }
1.37 veillard 857: while ((*cur != '\0') && (*cur != '/')) cur++;
858: filename = cur;
859: } else
860: cur++;
861: }
862: if (cur != filename)
863: rpmAddRealFile(dir->root, filename, rpm);
864: }
1.17 veillard 865:
866: /* Register this package */
867: rpmAddSoftware(rpm);
1.7 veillard 868:
869: /* dump the HTML related to this package */
1.56 daniel 870: if ((rpm2html_dump_html) && (dir->html))
1.40 httpng 871: dumpRpmHtml(rpm, tree);
872: if (rpm2html_dump_rdf)
873: dumpRpmRdf(rpm, tree);
1.7 veillard 874:
1.58 daniel 875: /* free the extra data */
876: rpmFreeExtraData(rpm);
1.8 veillard 877:
878: /* increment the counters */
1.11 veillard 879: if (installed) {
880: rpm2html_install_files++;
1.21 veillard 881: rpm2html_install_size += rpm->size / 1024;
1.11 veillard 882: } else {
883: rpm2html_files++;
1.21 veillard 884: rpm2html_size += rpm->size / 1024;
1.11 veillard 885: }
1.7 veillard 886:
1.32 veillard 887: return(rpm);
1.11 veillard 888: }
889:
890: /*
891: * rpmOpen : open an RPM file, read and parse the header and
892: * fill the informations in the database.
893: */
1.35 veillard 894: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32 veillard 895: rpmDataPtr cur;
1.64 daniel 896: #if defined(HAVE_RPM_RPMIO_H)
897: FD_t fd;
898: #else
1.11 veillard 899: int fd;
1.64 daniel 900: #define fdOpen(_a, _b, _c) open((_a), (_b))
901: #define fdClose(_a) close(_a)
902: #endif
1.11 veillard 903: int rc;
904: Header h = NULL;
1.83 veillard 905: Header s = NULL;
906: struct rpmlead lead;
1.11 veillard 907: int isSource;
908: char buffer[500];
1.20 veillard 909: struct stat buf;
1.86 veillard 910: #if defined(WITH_GPG)
911: FD_t ofd = NULL;
912: char *sigtarget = NULL;
913: ssize_t count;
914: unsigned char stbuffer[8192];
915: #endif
1.11 veillard 916:
917: /* open the file for reading */
1.35 veillard 918: if (tree->htmlpath[0] != '\0')
1.66 daniel 919: snprintf(buffer, sizeof(buffer), "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24 veillard 920: else
1.66 daniel 921: snprintf(buffer, sizeof(buffer), "%s/%s", dir->rpmdir, nameRpm);
1.72 daniel 922:
1.78 daniel 923: if (access(buffer, R_OK) < 0) {
924: fprintf(stderr, "open of %s failed: %s\n", buffer,
925: strerror(errno));
926: return(NULL);
927: }
1.72 daniel 928: #if defined(USE_RPMIO)
929: fd = Fopen(buffer, "r.fdio");
930: if (fd == NULL || Ferror(fd)) {
931: fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
932: Fstrerror(fd));
933: return(NULL);
934: }
935: #else
1.64 daniel 936: if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
1.11 veillard 937: fprintf(stderr, "open of %s failed: %s\n", buffer,
938: strerror(errno));
1.32 veillard 939: return(NULL);
1.11 veillard 940: }
1.72 daniel 941: #endif
1.11 veillard 942:
1.20 veillard 943: stat(buffer, &buf);
944:
1.11 veillard 945: /* read the RPM header */
946: rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
947: switch (rc) {
948: case 0:
949: if (!h) {
950: fprintf(stderr,
951: "old format source packages cannot be queried\n");
1.68 veillard 952: fdClose(fd);
1.32 veillard 953: return(NULL);
1.11 veillard 954: }
955: break;
956: case 1:
957: fprintf(stderr, "%s does not appear to be a RPM package\n",
958: nameRpm);
1.68 veillard 959: fdClose(fd);
1.32 veillard 960: return(NULL);
1.11 veillard 961: case 2:
962: fprintf(stderr, "query of %s failed\n", nameRpm);
1.68 veillard 963: fdClose(fd);
1.32 veillard 964: return(NULL);
1.11 veillard 965: default:
966: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
967: nameRpm, rc);
1.68 veillard 968: fdClose(fd);
1.32 veillard 969: return(NULL);
1.11 veillard 970: }
971:
972:
1.83 veillard 973: /* close the descriptor */
974: #if defined(USE_RPMIO)
975: Fclose(fd);
976: #else
977: fdClose(fd);
978: #endif
979:
980: /* XXX I do not know whether it is necessary to open the file twice */
981: /* open the file for reading */
982: #if defined(USE_RPMIO)
983: fd = Fopen(buffer, "r.fdio");
984: if (fd == NULL || Ferror(fd)) {
985: fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
986: Fstrerror(fd));
987: return(NULL);
988: }
989: #else
990: if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
991: fprintf(stderr, "open of %s failed: %s\n", buffer,
992: strerror(errno));
993: return(NULL);
994: }
995: #endif
996:
997: /* read the RPM signature */
998: if (readLead(fd, &lead)) {
999: fprintf(stderr, "readLead failed\n");
1000: fdClose(fd);
1001: return(NULL);
1002: }
1003: switch (lead.major) {
1004: case 1:
1005: fprintf(stderr, "no signature available (v1.0 RPM) in %s\n", nameRpm);
1006: break;
1007: default:
1008: if (rpmReadSignature(fd, &s, lead.signature_type)) {
1009: fprintf(stderr, "rpmReadSignature failed\n");
1010: fdClose(fd);
1011: return(NULL);
1012: }
1013: if (!s) {
1014: fprintf(stderr, "no signature available in %s\n", nameRpm);
1015: fdClose(fd);
1016: return(NULL);
1017: }
1.86 veillard 1018: #if defined(WITH_GPG)
1019: /* open temp file for writing */
1.93 veillard 1020: sigtarget = xmlMalloc(30);
1.86 veillard 1021: strcpy(sigtarget, "/tmp/rpm2html.date.XXXXXX");
1022: sigtarget = mktemp(sigtarget);
1023: ofd = Fopen(sigtarget, "w.ufdio");
1024: if (ofd == NULL || Ferror(ofd)) {
1025: fprintf(stderr, "Fopen of %s failed: %s\n", sigtarget,
1026: Fstrerror(ofd));
1.93 veillard 1027: xmlFree(sigtarget);
1.86 veillard 1028: sigtarget = NULL;
1029: }
1030:
1031: /* write the header and archive to a temp file */
1032: while ((count = Fread(stbuffer, sizeof(stbuffer[0]), sizeof(stbuffer), fd)) > 0) {
1033: if (Fwrite(stbuffer, sizeof(stbuffer[0]), count, ofd) < 0) {
1034: fprintf(stderr, "%s: Fwrite failed: %s\n", sigtarget,
1035: Fstrerror(ofd));
1.93 veillard 1036: xmlFree(sigtarget);
1.86 veillard 1037: sigtarget = NULL;
1038: }
1039: }
1040: if (count < 0) {
1041: fprintf(stderr, "%s: Fread failed: %s\n", buffer, Fstrerror(fd));
1.93 veillard 1042: xmlFree(sigtarget);
1.86 veillard 1043: sigtarget = NULL;
1044: }
1045:
1046: Fclose(ofd);
1047: #endif
1.83 veillard 1048: break;
1049: }
1050:
1051: /* close the descriptor */
1.72 daniel 1052: #if defined(USE_RPMIO)
1053: Fclose(fd);
1054: #else
1.64 daniel 1055: fdClose(fd);
1.72 daniel 1056: #endif
1.1 veillard 1057:
1.86 veillard 1058: #if defined(WITH_GPG)
1059: cur = rpmAnalyze(buffer, nameRpm, sigtarget, h, s, dir, tree, buf.st_mtime, isSource);
1060: #else
1061: cur = rpmAnalyze(buffer, nameRpm, NULL, h, s, dir, tree, buf.st_mtime, isSource);
1062: #endif
1.83 veillard 1063:
1064: /* free the header */
1065: headerFree(h);
1066: headerFree(s);
1067:
1.86 veillard 1068: #if defined(WITH_GPG)
1069: if (sigtarget) {
1070: unlink(sigtarget);
1.93 veillard 1071: xmlFree(sigtarget);
1.86 veillard 1072: }
1073: #endif
1074:
1.32 veillard 1075: return(cur);
1.6 veillard 1076: }
1077:
1078: /*
1.22 veillard 1079: * Scan one directory for RPM files this is where the recursive handling
1080: * is done.
1.6 veillard 1081: */
1.35 veillard 1082: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1083: rpmSubdirPtr subtree;
1.32 veillard 1084: rpmDataPtr ret = NULL, cur;
1.7 veillard 1085: char *filename;
1.22 veillard 1086: static char path[2000];
1.23 veillard 1087: struct stat buf;
1.7 veillard 1088: int len;
1.39 veillard 1089: DIR *d;
1090: struct dirent *file;
1.6 veillard 1091:
1.24 veillard 1092:
1093: /*
1094: * Create the directory for the HTML pages
1095: */
1.56 daniel 1096: if ((rpm2html_dump_html) && (dir->html)) {
1.45 veillard 1097: if (tree->htmlpath[0] != '\0')
1.66 daniel 1098: snprintf(path, sizeof(path), "%s/%s", dir->dir, tree->htmlpath);
1.45 veillard 1099: else
1.66 daniel 1100: snprintf(path, sizeof(path), "%s", dir->dir);
1.45 veillard 1101: createDirectory(path);
1102: }
1.43 veillard 1103:
1104: /*
1105: * Create the directory for the RDF pages
1106: if (rpm2html_rdf_dir != NULL) {
1107: if (tree->htmlpath[0] != '\0')
1.66 daniel 1108: snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
1.43 veillard 1109: else
1.66 daniel 1110: snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.43 veillard 1111: createDirectory(path);
1112: }
1.47 veillard 1113: */
1.24 veillard 1114:
1115: /*
1116: * Scan the repository.
1117: */
1.35 veillard 1118: if (tree->rpmpath[0] != '\0')
1.66 daniel 1119: snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, tree->rpmpath);
1.24 veillard 1120: else
1.66 daniel 1121: snprintf(path, sizeof(path), "%s", dir->rpmdir);
1.51 veillard 1122: if (rpm2htmlVerbose > 1)
1.66 daniel 1123: printf("Scanning directory %s\n", path);
1.24 veillard 1124:
1.39 veillard 1125: d = opendir(path);
1126: if (d == NULL) {
1.24 veillard 1127: fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6 veillard 1128: strerror(errno));
1.35 veillard 1129: rpmRemoveSubdir(tree);
1.36 veillard 1130: rpmFreeSubdir(tree);
1.94 daniel 1131: tree = NULL;
1.32 veillard 1132: return(NULL);
1.6 veillard 1133: } else {
1.39 veillard 1134: while ((file = readdir(d)) != NULL) {
1.32 veillard 1135: cur = NULL;
1.39 veillard 1136: filename = file->d_name;
1.7 veillard 1137: len = strlen(filename);
1.24 veillard 1138:
1139: /*
1140: * Compute the full path
1141: */
1.35 veillard 1142: if (tree->rpmpath[0] != '\0')
1.66 daniel 1143: snprintf(path, sizeof(path), "%s/%s/%s", dir->rpmdir, tree->rpmpath,
1.35 veillard 1144: filename);
1.22 veillard 1145: else
1.66 daniel 1146: snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, filename);
1.22 veillard 1147:
1148: /*
1.25 veillard 1149: * Stat() the file to detect directory and symlimks
1150: */
1.30 veillard 1151: if (lstat(path, &buf) != 0) {
1.25 veillard 1152: fprintf(stderr, "Couldn't stat(%s)\n", path);
1153: continue;
1154: }
1.35 veillard 1155:
1.25 veillard 1156: /*
1.23 veillard 1157: * Check for RPM files by looking at the suffix
1.54 veillard 1158: * Note that SuSE source RPMs have a ".spm" suffix
1.63 daniel 1159: * We may or may not follow symlinks to RPM files
1.22 veillard 1160: */
1.63 daniel 1161: if (((len >= 5) &&
1.54 veillard 1162: (!strcasecmp(&filename[len - 4], ".rpm"))) ||
1163: ((len >= 5) &&
1164: (!strcasecmp(&filename[len - 4], ".spm")))) {
1.63 daniel 1165:
1.65 daniel 1166: if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) {
1.66 daniel 1167: if (rpm2htmlVerbose > 1)
1.63 daniel 1168: fprintf(stderr, "Dropping symlink %s\n", path);
1169: continue;
1170: }
1.35 veillard 1171: cur = rpmOpen(filename, dir, tree);
1.63 daniel 1172: }
1173:
1174: /*
1175: * Don't follow of analyze symlinks,
1176: */
1.65 daniel 1177: else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0)) {
1.66 daniel 1178: if (rpm2htmlVerbose > 1)
1.63 daniel 1179: fprintf(stderr, "Dropping symlink %s\n", path);
1180: continue;
1.44 veillard 1181: }
1182:
1183: /*
1184: * Check for RDF files by looking at the suffix
1185: */
1186: else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
1187: cur = rpmOpenRdf(filename, dir, tree);
1.22 veillard 1188: }
1.35 veillard 1189:
1.22 veillard 1190: /*
1.23 veillard 1191: * Else if this is a directory, recurse !
1.22 veillard 1192: */
1.25 veillard 1193: else if (S_ISDIR(buf.st_mode)) {
1194: if (filename[0] != '.') {
1.57 daniel 1195: subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
1.35 veillard 1196: cur = rpmOneDirScan(dir, subtree);
1.25 veillard 1197: }
1.22 veillard 1198: }
1.32 veillard 1199: if (cur != NULL) ret = rpmAddList(ret, cur);
1.7 veillard 1200: }
1.6 veillard 1201: }
1.39 veillard 1202: closedir(d);
1.33 veillard 1203:
1204: /*
1205: * Dump the pages related to this directory.
1206: */
1.35 veillard 1207: if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36 veillard 1208: else {
1209: rpmRemoveSubdir(tree);
1210: rpmFreeSubdir(tree);
1.94 daniel 1211: tree = NULL;
1.36 veillard 1212: }
1.35 veillard 1213:
1.32 veillard 1214: return(ret);
1.22 veillard 1215: }
1216:
1217: /*
1218: * Scan a directory for RPM files.
1219: */
1.35 veillard 1220: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37 veillard 1221: rpmSubdirPtr cur;
1222: rpmDataPtr ret;
1223:
1.56 daniel 1224: if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
1.37 veillard 1225: dir->root = rpmCreateRealRoot();
1226: }
1227: cur = rpmNewSubdir(tree, dir->name,
1.57 daniel 1228: dir->subdir == NULL ? "" : dir->subdir, "", dir->color,
1229: dir->html);
1.37 veillard 1230: ret = rpmOneDirScan(dir, cur);
1.38 veillard 1231: rpmDumpHtmlRealRoot(dir);
1.37 veillard 1232: return(ret);
1.6 veillard 1233: }
1234:
1235: /*
1.11 veillard 1236: * Scan the local RPM database for RPM files.
1237: */
1.32 veillard 1238: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37 veillard 1239: static char path[2000];
1.32 veillard 1240: rpmDataPtr ret = NULL, cur;
1.11 veillard 1241: rpmdb db;
1242: Header h = NULL;
1.72 daniel 1243: #ifndef USE_RPMIO
1.32 veillard 1244: int offset;
1.71 daniel 1245: #endif
1.11 veillard 1246: char *prefix = "/";
1.88 veillard 1247:
1248: #ifdef WITH_SQL
1249: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1250: #endif
1.11 veillard 1251:
1.37 veillard 1252: /*
1253: * Create the directory for the HTML pages
1254: */
1.56 daniel 1255: if ((rpm2html_dump_html) && (dir->html)) {
1.45 veillard 1256: if (dir->subdir)
1.66 daniel 1257: snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir);
1.45 veillard 1258: else
1.66 daniel 1259: snprintf(path, sizeof(path), "%s", dir->dir);
1.45 veillard 1260: createDirectory(path);
1261: }
1262:
1263: /*
1264: * Create the directory for the RDF pages
1265: */
1266: if (rpm2html_rdf_dir != NULL) {
1267: if (dir->subdir)
1.66 daniel 1268: snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, dir->subdir);
1.45 veillard 1269: else
1.66 daniel 1270: snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.45 veillard 1271: createDirectory(path);
1272: }
1.37 veillard 1273:
1.66 daniel 1274: if (rpm2htmlVerbose)
1275: printf("Scanning the database of installed RPMs\n");
1.70 daniel 1276:
1277: if (dir->dbpath != NULL)
1278: addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7); /* Added by A.Gibert */
1.66 daniel 1279:
1.11 veillard 1280: if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32 veillard 1281: return(NULL);
1.11 veillard 1282: }
1.71 daniel 1283:
1.72 daniel 1284: #ifdef USE_RPMIO
1.71 daniel 1285: { rpmdbMatchIterator mi;
1286: mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
1287: while ((h = rpmdbNextIterator(mi)) != NULL) {
1.86 veillard 1288: cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.71 daniel 1289: if (cur != NULL) ret = rpmAddList(ret, cur);
1290: }
1291: rpmdbFreeIterator(mi);
1292: }
1.72 daniel 1293: #else /* USE_RPMIO */
1.11 veillard 1294: offset = rpmdbFirstRecNum(db);
1295: while (offset) {
1296: h = rpmdbGetRecord(db, offset);
1297: if (!h) {
1298: fprintf(stderr, "could not read database record!\n");
1.32 veillard 1299: return(ret);
1.11 veillard 1300: }
1.86 veillard 1301: cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.32 veillard 1302: if (cur != NULL) ret = rpmAddList(ret, cur);
1.11 veillard 1303: headerFree(h);
1304: offset = rpmdbNextRecNum(db, offset);
1305: }
1.72 daniel 1306: #endif /* USE_RPMIO */
1.71 daniel 1307:
1.11 veillard 1308: rpmdbClose(db);
1309:
1.32 veillard 1310: return(ret);
1.95 ! daniel 1311: }
! 1312:
! 1313: /*
! 1314: * Scan one directory only
! 1315: */
! 1316:
! 1317: void rpmDirScanOneDir(const char *directory) {
! 1318: rpmDirPtr dir;
! 1319: rpmDataPtr cur;
! 1320:
! 1321: /*
! 1322: * first try to find the distrib
! 1323: */
! 1324: dir = dirList;
! 1325: while (dir != NULL) {
! 1326: if (!strcasecmp(dir->rpmdir, directory))
! 1327: break;
! 1328: dir = dir->next;
! 1329: }
! 1330: if (dir == NULL) {
! 1331: fprintf(stderr, "rpmDirScanOneDir(%s): distribution not found\n",
! 1332: directory);
! 1333: return;
! 1334: }
! 1335: if (rpm2htmlVerbose)
! 1336: printf("indexing %s\n", dir->name);
! 1337:
! 1338: /*
! 1339: * Allocate a directory tree.
! 1340: */
! 1341: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
! 1342:
! 1343: cur = NULL;
! 1344:
! 1345: /*
! 1346: * Override default setting.
! 1347: */
! 1348: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
! 1349: dir->maint = xmlStrdup(rpm2html_maint);
! 1350: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
! 1351: dir->mail = xmlStrdup(rpm2html_mail);
! 1352: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
! 1353: dir->ftp = xmlStrdup(rpm2html_ftp);
! 1354: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
! 1355: dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
! 1356: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
! 1357: dir->dir = xmlStrdup(rpm2html_dir);
! 1358: if ((dir->host == NULL) && (rpm2html_host != NULL))
! 1359: dir->host = xmlStrdup(rpm2html_host);
! 1360: if ((dir->name == NULL) && (rpm2html_name != NULL))
! 1361: dir->name = xmlStrdup(rpm2html_name);
! 1362: if ((dir->url == NULL) && (rpm2html_url != NULL))
! 1363: dir->url = xmlStrdup(rpm2html_url);
! 1364:
! 1365: if (dir->rpmdir == NULL) {
! 1366: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
! 1367: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
! 1368: /* Scan the local RPM database instead of a directory */
! 1369: cur = rpmBaseScan(dir);
! 1370: } else if (dir->ftp == NULL) {
! 1371: fprintf(stderr, "Directory %s disabled : no ftp field\n",
! 1372: dir->rpmdir);
! 1373: } else {
! 1374: #ifdef WITH_SQL
! 1375: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
! 1376: #endif
! 1377: if (rpm2htmlVerbose)
! 1378: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
! 1379: cur = rpmDirScan(dir, dirTree);
! 1380: }
! 1381:
! 1382: if (dir->root != NULL) {
! 1383: rpmDestroyRealRoot(dir->root);
! 1384: dir->root = NULL;
! 1385: }
! 1386: rpmFreeSubdir(dirTree);
! 1387: dirTree = NULL;
1.80 veillard 1388: }
1389:
1390:
1391: /*
1392: * Scan one distribution only
1393: */
1394:
1395: void rpmDirScanOneDist(const char *dist) {
1396: rpmDirPtr dir;
1397: rpmDataPtr cur;
1398:
1399: /*
1400: * first try to find the distrib
1401: */
1402: dir = dirList;
1403: while (dir != NULL) {
1404: if (!strcasecmp(dir->name, dist))
1405: break;
1406: if (!strcasecmp(dir->subdir, dist))
1407: break;
1408: if (!strcasecmp(dir->rpmdir, dist))
1409: break;
1410: dir = dir->next;
1411: }
1412: if (dir == NULL) {
1413: dir = dirList;
1414: while (dir != NULL) {
1415: if (!strstr(dir->name, dist))
1416: break;
1417: if (!strstr(dir->subdir, dist))
1418: break;
1419: if (!strstr(dir->rpmdir, dist))
1420: break;
1421: dir = dir->next;
1422: }
1423: }
1424: if (dir == NULL) {
1425: fprintf(stderr, "rpmDirScanOneDist(%s): distribution not found\n",
1426: dist);
1427: return;
1428: }
1429: if (rpm2htmlVerbose)
1430: printf("indexing %s\n", dir->name);
1431:
1432: /*
1433: * Allocate a directory tree.
1434: */
1435: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1436:
1437: cur = NULL;
1438:
1439: /*
1440: * Override default setting.
1441: */
1442: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.93 veillard 1443: dir->maint = xmlStrdup(rpm2html_maint);
1.80 veillard 1444: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.93 veillard 1445: dir->mail = xmlStrdup(rpm2html_mail);
1.80 veillard 1446: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.93 veillard 1447: dir->ftp = xmlStrdup(rpm2html_ftp);
1.80 veillard 1448: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.93 veillard 1449: dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
1.80 veillard 1450: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.93 veillard 1451: dir->dir = xmlStrdup(rpm2html_dir);
1.80 veillard 1452: if ((dir->host == NULL) && (rpm2html_host != NULL))
1.93 veillard 1453: dir->host = xmlStrdup(rpm2html_host);
1.80 veillard 1454: if ((dir->name == NULL) && (rpm2html_name != NULL))
1.93 veillard 1455: dir->name = xmlStrdup(rpm2html_name);
1.80 veillard 1456: if ((dir->url == NULL) && (rpm2html_url != NULL))
1.93 veillard 1457: dir->url = xmlStrdup(rpm2html_url);
1.80 veillard 1458:
1459: if (dir->rpmdir == NULL) {
1460: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1461: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1462: /* Scan the local RPM database instead of a directory */
1463: cur = rpmBaseScan(dir);
1464: } else if (dir->ftp == NULL) {
1465: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1466: dir->rpmdir);
1467: } else {
1.82 veillard 1468: #ifdef WITH_SQL
1.80 veillard 1469: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82 veillard 1470: #endif
1.80 veillard 1471: if (rpm2htmlVerbose)
1472: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1473: cur = rpmDirScan(dir, dirTree);
1474: }
1475:
1476: if (dir->root != NULL) {
1477: rpmDestroyRealRoot(dir->root);
1478: dir->root = NULL;
1479: }
1.93 veillard 1480: rpmFreeSubdir(dirTree);
1.94 daniel 1481: dirTree = NULL;
1.11 veillard 1482: }
1483:
1484: /*
1.6 veillard 1485: * Scan all registered directories.
1486: * One fist check for completeness of the informations in
1487: * the rpmDir structure.
1488: */
1489:
1.32 veillard 1490: rpmDataPtr rpmDirScanAll(void) {
1.18 veillard 1491: rpmDirPtr dir, next;
1.32 veillard 1492: rpmDataPtr ret = NULL, cur;
1.91 veillard 1493: #ifndef WITH_SQL
1.46 veillard 1494: int maxLists = 50;
1495: rpmDataPtr *rpmLists;
1.35 veillard 1496: int nbLists = 0;
1497: int i;
1.91 veillard 1498: #endif
1.18 veillard 1499:
1500: /*
1501: * first reverse the list ....
1502: */
1503: dir = dirList;
1504: dirList = NULL;
1505: while (dir != NULL) {
1506: next = dir->next;
1507: dir->next = dirList;
1508: dirList = dir;
1509: dir = next;
1510: }
1.57 daniel 1511: dir = dirList;
1.18 veillard 1512:
1.35 veillard 1513: /*
1514: * Allocate a directory tree.
1515: */
1.57 daniel 1516: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1.6 veillard 1517:
1.91 veillard 1518: #ifndef WITH_SQL
1.93 veillard 1519: rpmLists = (rpmDataPtr *) xmlMalloc(maxLists * sizeof(rpmDataPtr));
1.46 veillard 1520: if (rpmLists == NULL) {
1521: fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
1522: exit(1);
1523: }
1.91 veillard 1524: #endif
1.46 veillard 1525:
1.6 veillard 1526: while (dir != NULL) {
1.32 veillard 1527: cur = NULL;
1528:
1.14 veillard 1529: /*
1.91 veillard 1530: * Complete with default setting.
1.14 veillard 1531: */
1.15 veillard 1532: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.93 veillard 1533: dir->maint = xmlStrdup(rpm2html_maint);
1.15 veillard 1534: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.93 veillard 1535: dir->mail = xmlStrdup(rpm2html_mail);
1.15 veillard 1536: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.93 veillard 1537: dir->ftp = xmlStrdup(rpm2html_ftp);
1.15 veillard 1538: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.93 veillard 1539: dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
1.15 veillard 1540: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.93 veillard 1541: dir->dir = xmlStrdup(rpm2html_dir);
1.15 veillard 1542: if ((dir->host == NULL) && (rpm2html_host != NULL))
1.93 veillard 1543: dir->host = xmlStrdup(rpm2html_host);
1.15 veillard 1544: if ((dir->name == NULL) && (rpm2html_name != NULL))
1.93 veillard 1545: dir->name = xmlStrdup(rpm2html_name);
1.15 veillard 1546: if ((dir->url == NULL) && (rpm2html_url != NULL))
1.93 veillard 1547: dir->url = xmlStrdup(rpm2html_url);
1.14 veillard 1548:
1549: if (dir->rpmdir == NULL) {
1.6 veillard 1550: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.91 veillard 1551: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1.11 veillard 1552: /* Scan the local RPM database instead of a directory */
1.32 veillard 1553: cur = rpmBaseScan(dir);
1.7 veillard 1554: } else if (dir->ftp == NULL) {
1555: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14 veillard 1556: dir->rpmdir);
1.6 veillard 1557: } else {
1.82 veillard 1558: #ifdef WITH_SQL
1.79 veillard 1559: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82 veillard 1560: #endif
1.51 veillard 1561: if (rpm2htmlVerbose)
1.66 daniel 1562: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1.35 veillard 1563: cur = rpmDirScan(dir, dirTree);
1.6 veillard 1564: }
1565:
1.91 veillard 1566: #ifdef WITH_SQL
1567: /*
1568: * The packages list will be reextratced from the
1569: * database at the end, minimize memory consumption
1570: */
1571: rpmlistCleanup();
1572: #else
1.35 veillard 1573: if (cur != NULL) {
1.46 veillard 1574: if (nbLists >= maxLists) {
1575: maxLists *= 2;
1.93 veillard 1576: rpmLists = (rpmDataPtr *) xmlRealloc(rpmLists,
1.46 veillard 1577: maxLists * sizeof(rpmDataPtr));
1578: if (rpmLists == NULL) {
1579: fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
1580: exit(1);
1.35 veillard 1581: }
1582: }
1.46 veillard 1583: rpmLists[nbLists] = cur;
1584: nbLists++;
1.39 veillard 1585: }
1.91 veillard 1586: #endif
1.39 veillard 1587: if (dir->root != NULL) {
1.48 veillard 1588: rpmDestroyRealRoot(dir->root);
1589: dir->root = NULL;
1.35 veillard 1590: }
1.6 veillard 1591: dir = dir->next;
1592: }
1.91 veillard 1593: #ifndef WITH_SQL
1.35 veillard 1594: for (i = 0;i < nbLists;i++)
1595: ret = rpmAddList(ret, rpmLists[i]);
1.93 veillard 1596: xmlFree(rpmLists);
1.91 veillard 1597: #endif
1.32 veillard 1598: return(ret);
1.60 daniel 1599: }
1600:
1601: /*
1602: * Cleanup the global variables from this module
1603: */
1604: void rpmopenCleanup(void) {
1605: if (buffer != NULL)
1.93 veillard 1606: xmlFree(buffer);
1.60 daniel 1607: buffer = NULL;
1608: buffer_size = 50 * 1024 * sizeof(char);
1.1 veillard 1609: }
1610:
Webmaster