Annotation of rpm2html/rpmopen.c, revision 1.97
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.97 ! daniel 6: * $Id: rpmopen.c,v 1.96 2001/02/07 09:04:42 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.96 daniel 1177: else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0) &&
1178: (strcmp(dir->rpmdir, path))) {
1.66 daniel 1179: if (rpm2htmlVerbose > 1)
1.63 daniel 1180: fprintf(stderr, "Dropping symlink %s\n", path);
1181: continue;
1.44 veillard 1182: }
1183:
1184: /*
1185: * Check for RDF files by looking at the suffix
1186: */
1187: else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
1188: cur = rpmOpenRdf(filename, dir, tree);
1.22 veillard 1189: }
1.35 veillard 1190:
1.22 veillard 1191: /*
1.23 veillard 1192: * Else if this is a directory, recurse !
1.22 veillard 1193: */
1.25 veillard 1194: else if (S_ISDIR(buf.st_mode)) {
1195: if (filename[0] != '.') {
1.57 daniel 1196: subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
1.35 veillard 1197: cur = rpmOneDirScan(dir, subtree);
1.25 veillard 1198: }
1.22 veillard 1199: }
1.32 veillard 1200: if (cur != NULL) ret = rpmAddList(ret, cur);
1.7 veillard 1201: }
1.6 veillard 1202: }
1.39 veillard 1203: closedir(d);
1.33 veillard 1204:
1205: /*
1206: * Dump the pages related to this directory.
1207: */
1.35 veillard 1208: if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36 veillard 1209: else {
1210: rpmRemoveSubdir(tree);
1211: rpmFreeSubdir(tree);
1.94 daniel 1212: tree = NULL;
1.36 veillard 1213: }
1.35 veillard 1214:
1.32 veillard 1215: return(ret);
1.22 veillard 1216: }
1217:
1218: /*
1219: * Scan a directory for RPM files.
1220: */
1.35 veillard 1221: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37 veillard 1222: rpmSubdirPtr cur;
1223: rpmDataPtr ret;
1224:
1.56 daniel 1225: if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
1.37 veillard 1226: dir->root = rpmCreateRealRoot();
1227: }
1228: cur = rpmNewSubdir(tree, dir->name,
1.57 daniel 1229: dir->subdir == NULL ? "" : dir->subdir, "", dir->color,
1230: dir->html);
1.37 veillard 1231: ret = rpmOneDirScan(dir, cur);
1.38 veillard 1232: rpmDumpHtmlRealRoot(dir);
1.37 veillard 1233: return(ret);
1.6 veillard 1234: }
1235:
1236: /*
1.11 veillard 1237: * Scan the local RPM database for RPM files.
1238: */
1.32 veillard 1239: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37 veillard 1240: static char path[2000];
1.32 veillard 1241: rpmDataPtr ret = NULL, cur;
1.11 veillard 1242: rpmdb db;
1243: Header h = NULL;
1.72 daniel 1244: #ifndef USE_RPMIO
1.32 veillard 1245: int offset;
1.71 daniel 1246: #endif
1.11 veillard 1247: char *prefix = "/";
1.88 veillard 1248:
1249: #ifdef WITH_SQL
1250: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1251: #endif
1.11 veillard 1252:
1.37 veillard 1253: /*
1254: * Create the directory for the HTML pages
1255: */
1.56 daniel 1256: if ((rpm2html_dump_html) && (dir->html)) {
1.45 veillard 1257: if (dir->subdir)
1.66 daniel 1258: snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir);
1.45 veillard 1259: else
1.66 daniel 1260: snprintf(path, sizeof(path), "%s", dir->dir);
1.45 veillard 1261: createDirectory(path);
1262: }
1263:
1264: /*
1265: * Create the directory for the RDF pages
1266: */
1267: if (rpm2html_rdf_dir != NULL) {
1268: if (dir->subdir)
1.66 daniel 1269: snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, dir->subdir);
1.45 veillard 1270: else
1.66 daniel 1271: snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.45 veillard 1272: createDirectory(path);
1273: }
1.37 veillard 1274:
1.66 daniel 1275: if (rpm2htmlVerbose)
1276: printf("Scanning the database of installed RPMs\n");
1.70 daniel 1277:
1278: if (dir->dbpath != NULL)
1279: addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7); /* Added by A.Gibert */
1.66 daniel 1280:
1.11 veillard 1281: if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32 veillard 1282: return(NULL);
1.11 veillard 1283: }
1.71 daniel 1284:
1.72 daniel 1285: #ifdef USE_RPMIO
1.71 daniel 1286: { rpmdbMatchIterator mi;
1287: mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
1288: while ((h = rpmdbNextIterator(mi)) != NULL) {
1.86 veillard 1289: cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.71 daniel 1290: if (cur != NULL) ret = rpmAddList(ret, cur);
1291: }
1292: rpmdbFreeIterator(mi);
1293: }
1.72 daniel 1294: #else /* USE_RPMIO */
1.11 veillard 1295: offset = rpmdbFirstRecNum(db);
1296: while (offset) {
1297: h = rpmdbGetRecord(db, offset);
1298: if (!h) {
1299: fprintf(stderr, "could not read database record!\n");
1.32 veillard 1300: return(ret);
1.11 veillard 1301: }
1.86 veillard 1302: cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.32 veillard 1303: if (cur != NULL) ret = rpmAddList(ret, cur);
1.11 veillard 1304: headerFree(h);
1305: offset = rpmdbNextRecNum(db, offset);
1306: }
1.72 daniel 1307: #endif /* USE_RPMIO */
1.71 daniel 1308:
1.11 veillard 1309: rpmdbClose(db);
1310:
1.32 veillard 1311: return(ret);
1.95 daniel 1312: }
1313:
1314: /*
1315: * Scan one directory only
1316: */
1317:
1318: void rpmDirScanOneDir(const char *directory) {
1319: rpmDirPtr dir;
1320: rpmDataPtr cur;
1321:
1322: /*
1323: * first try to find the distrib
1324: */
1325: dir = dirList;
1326: while (dir != NULL) {
1327: if (!strcasecmp(dir->rpmdir, directory))
1328: break;
1329: dir = dir->next;
1330: }
1331: if (dir == NULL) {
1332: fprintf(stderr, "rpmDirScanOneDir(%s): distribution not found\n",
1333: directory);
1334: return;
1335: }
1336: if (rpm2htmlVerbose)
1337: printf("indexing %s\n", dir->name);
1338:
1339: /*
1340: * Allocate a directory tree.
1341: */
1342: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1343:
1344: cur = NULL;
1345:
1346: /*
1347: * Override default setting.
1348: */
1349: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1350: dir->maint = xmlStrdup(rpm2html_maint);
1351: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1352: dir->mail = xmlStrdup(rpm2html_mail);
1353: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1354: dir->ftp = xmlStrdup(rpm2html_ftp);
1355: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1356: dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
1357: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1358: dir->dir = xmlStrdup(rpm2html_dir);
1359: if ((dir->host == NULL) && (rpm2html_host != NULL))
1360: dir->host = xmlStrdup(rpm2html_host);
1361: if ((dir->name == NULL) && (rpm2html_name != NULL))
1362: dir->name = xmlStrdup(rpm2html_name);
1363: if ((dir->url == NULL) && (rpm2html_url != NULL))
1364: dir->url = xmlStrdup(rpm2html_url);
1365:
1366: if (dir->rpmdir == NULL) {
1367: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1368: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1369: /* Scan the local RPM database instead of a directory */
1370: cur = rpmBaseScan(dir);
1371: } else if (dir->ftp == NULL) {
1372: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1373: dir->rpmdir);
1374: } else {
1375: #ifdef WITH_SQL
1376: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1377: #endif
1378: if (rpm2htmlVerbose)
1379: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1380: cur = rpmDirScan(dir, dirTree);
1381: }
1382:
1.97 ! daniel 1383: #if 0
1.95 daniel 1384: if (dir->root != NULL) {
1385: rpmDestroyRealRoot(dir->root);
1386: dir->root = NULL;
1387: }
1388: rpmFreeSubdir(dirTree);
1389: dirTree = NULL;
1.97 ! daniel 1390: #endif
1.80 veillard 1391: }
1392:
1393:
1394: /*
1395: * Scan one distribution only
1396: */
1397:
1398: void rpmDirScanOneDist(const char *dist) {
1399: rpmDirPtr dir;
1400: rpmDataPtr cur;
1401:
1402: /*
1403: * first try to find the distrib
1404: */
1405: dir = dirList;
1406: while (dir != NULL) {
1407: if (!strcasecmp(dir->name, dist))
1408: break;
1409: if (!strcasecmp(dir->subdir, dist))
1410: break;
1411: if (!strcasecmp(dir->rpmdir, dist))
1412: break;
1413: dir = dir->next;
1414: }
1415: if (dir == NULL) {
1416: dir = dirList;
1417: while (dir != NULL) {
1418: if (!strstr(dir->name, dist))
1419: break;
1420: if (!strstr(dir->subdir, dist))
1421: break;
1422: if (!strstr(dir->rpmdir, dist))
1423: break;
1424: dir = dir->next;
1425: }
1426: }
1427: if (dir == NULL) {
1428: fprintf(stderr, "rpmDirScanOneDist(%s): distribution not found\n",
1429: dist);
1430: return;
1431: }
1432: if (rpm2htmlVerbose)
1433: printf("indexing %s\n", dir->name);
1434:
1435: /*
1436: * Allocate a directory tree.
1437: */
1438: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1439:
1440: cur = NULL;
1441:
1442: /*
1443: * Override default setting.
1444: */
1445: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.93 veillard 1446: dir->maint = xmlStrdup(rpm2html_maint);
1.80 veillard 1447: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.93 veillard 1448: dir->mail = xmlStrdup(rpm2html_mail);
1.80 veillard 1449: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.93 veillard 1450: dir->ftp = xmlStrdup(rpm2html_ftp);
1.80 veillard 1451: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.93 veillard 1452: dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
1.80 veillard 1453: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.93 veillard 1454: dir->dir = xmlStrdup(rpm2html_dir);
1.80 veillard 1455: if ((dir->host == NULL) && (rpm2html_host != NULL))
1.93 veillard 1456: dir->host = xmlStrdup(rpm2html_host);
1.80 veillard 1457: if ((dir->name == NULL) && (rpm2html_name != NULL))
1.93 veillard 1458: dir->name = xmlStrdup(rpm2html_name);
1.80 veillard 1459: if ((dir->url == NULL) && (rpm2html_url != NULL))
1.93 veillard 1460: dir->url = xmlStrdup(rpm2html_url);
1.80 veillard 1461:
1462: if (dir->rpmdir == NULL) {
1463: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1464: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1465: /* Scan the local RPM database instead of a directory */
1466: cur = rpmBaseScan(dir);
1467: } else if (dir->ftp == NULL) {
1468: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1469: dir->rpmdir);
1470: } else {
1.82 veillard 1471: #ifdef WITH_SQL
1.80 veillard 1472: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82 veillard 1473: #endif
1.80 veillard 1474: if (rpm2htmlVerbose)
1475: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1476: cur = rpmDirScan(dir, dirTree);
1477: }
1478:
1479: if (dir->root != NULL) {
1480: rpmDestroyRealRoot(dir->root);
1481: dir->root = NULL;
1482: }
1.93 veillard 1483: rpmFreeSubdir(dirTree);
1.94 daniel 1484: dirTree = NULL;
1.11 veillard 1485: }
1486:
1487: /*
1.6 veillard 1488: * Scan all registered directories.
1489: * One fist check for completeness of the informations in
1490: * the rpmDir structure.
1491: */
1492:
1.32 veillard 1493: rpmDataPtr rpmDirScanAll(void) {
1.18 veillard 1494: rpmDirPtr dir, next;
1.32 veillard 1495: rpmDataPtr ret = NULL, cur;
1.91 veillard 1496: #ifndef WITH_SQL
1.46 veillard 1497: int maxLists = 50;
1498: rpmDataPtr *rpmLists;
1.35 veillard 1499: int nbLists = 0;
1500: int i;
1.91 veillard 1501: #endif
1.18 veillard 1502:
1503: /*
1504: * first reverse the list ....
1505: */
1506: dir = dirList;
1507: dirList = NULL;
1508: while (dir != NULL) {
1509: next = dir->next;
1510: dir->next = dirList;
1511: dirList = dir;
1512: dir = next;
1513: }
1.57 daniel 1514: dir = dirList;
1.18 veillard 1515:
1.35 veillard 1516: /*
1517: * Allocate a directory tree.
1518: */
1.57 daniel 1519: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1.6 veillard 1520:
1.91 veillard 1521: #ifndef WITH_SQL
1.93 veillard 1522: rpmLists = (rpmDataPtr *) xmlMalloc(maxLists * sizeof(rpmDataPtr));
1.46 veillard 1523: if (rpmLists == NULL) {
1524: fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
1525: exit(1);
1526: }
1.91 veillard 1527: #endif
1.46 veillard 1528:
1.6 veillard 1529: while (dir != NULL) {
1.32 veillard 1530: cur = NULL;
1531:
1.14 veillard 1532: /*
1.91 veillard 1533: * Complete with default setting.
1.14 veillard 1534: */
1.15 veillard 1535: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.93 veillard 1536: dir->maint = xmlStrdup(rpm2html_maint);
1.15 veillard 1537: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.93 veillard 1538: dir->mail = xmlStrdup(rpm2html_mail);
1.15 veillard 1539: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.93 veillard 1540: dir->ftp = xmlStrdup(rpm2html_ftp);
1.15 veillard 1541: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.93 veillard 1542: dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
1.15 veillard 1543: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.93 veillard 1544: dir->dir = xmlStrdup(rpm2html_dir);
1.15 veillard 1545: if ((dir->host == NULL) && (rpm2html_host != NULL))
1.93 veillard 1546: dir->host = xmlStrdup(rpm2html_host);
1.15 veillard 1547: if ((dir->name == NULL) && (rpm2html_name != NULL))
1.93 veillard 1548: dir->name = xmlStrdup(rpm2html_name);
1.15 veillard 1549: if ((dir->url == NULL) && (rpm2html_url != NULL))
1.93 veillard 1550: dir->url = xmlStrdup(rpm2html_url);
1.14 veillard 1551:
1552: if (dir->rpmdir == NULL) {
1.6 veillard 1553: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.91 veillard 1554: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1.11 veillard 1555: /* Scan the local RPM database instead of a directory */
1.32 veillard 1556: cur = rpmBaseScan(dir);
1.7 veillard 1557: } else if (dir->ftp == NULL) {
1558: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14 veillard 1559: dir->rpmdir);
1.6 veillard 1560: } else {
1.82 veillard 1561: #ifdef WITH_SQL
1.79 veillard 1562: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82 veillard 1563: #endif
1.51 veillard 1564: if (rpm2htmlVerbose)
1.66 daniel 1565: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1.35 veillard 1566: cur = rpmDirScan(dir, dirTree);
1.6 veillard 1567: }
1568:
1.91 veillard 1569: #ifdef WITH_SQL
1570: /*
1571: * The packages list will be reextratced from the
1572: * database at the end, minimize memory consumption
1573: */
1574: rpmlistCleanup();
1575: #else
1.35 veillard 1576: if (cur != NULL) {
1.46 veillard 1577: if (nbLists >= maxLists) {
1578: maxLists *= 2;
1.93 veillard 1579: rpmLists = (rpmDataPtr *) xmlRealloc(rpmLists,
1.46 veillard 1580: maxLists * sizeof(rpmDataPtr));
1581: if (rpmLists == NULL) {
1582: fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
1583: exit(1);
1.35 veillard 1584: }
1585: }
1.46 veillard 1586: rpmLists[nbLists] = cur;
1587: nbLists++;
1.39 veillard 1588: }
1.91 veillard 1589: #endif
1.39 veillard 1590: if (dir->root != NULL) {
1.48 veillard 1591: rpmDestroyRealRoot(dir->root);
1592: dir->root = NULL;
1.35 veillard 1593: }
1.6 veillard 1594: dir = dir->next;
1595: }
1.91 veillard 1596: #ifndef WITH_SQL
1.35 veillard 1597: for (i = 0;i < nbLists;i++)
1598: ret = rpmAddList(ret, rpmLists[i]);
1.93 veillard 1599: xmlFree(rpmLists);
1.91 veillard 1600: #endif
1.32 veillard 1601: return(ret);
1.60 daniel 1602: }
1603:
1604: /*
1605: * Cleanup the global variables from this module
1606: */
1607: void rpmopenCleanup(void) {
1608: if (buffer != NULL)
1.93 veillard 1609: xmlFree(buffer);
1.60 daniel 1610: buffer = NULL;
1611: buffer_size = 50 * 1024 * sizeof(char);
1.1 veillard 1612: }
1613:
Webmaster