Annotation of rpm2html/rpmopen.c, revision 1.91
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.91 ! veillard 6: * $Id: rpmopen.c,v 1.90 2000/11/26 22:14:43 veillard 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.61 daniel 74: if (extra->packager != NULL) debugFree(extra->packager);
75: if (extra->description != NULL) debugFree(extra->description);
76: if (extra->copyright != NULL) debugFree(extra->copyright);
77: if (extra->changelog != NULL) debugFree(extra->changelog);
78: if (extra->srcrpm != NULL) debugFree(extra->srcrpm);
79: if (extra->host != NULL) debugFree(extra->host);
80: if (extra->resources != NULL) debugFree(extra->resources);
81: if (extra->requires != NULL) debugFree(extra->requires);
82: if (extra->filelist != NULL) debugFree(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)
87: debugFree(extra->sigs[n1]->sig);
88: #if defined(WITH_GPG)
89: if (extra->sigs[n1]->resolve != NULL)
90: debugFree(extra->sigs[n1]->resolve);
91: #endif
1.83 veillard 92: debugFree(extra->sigs[n1]);
1.86 veillard 93: }
1.83 veillard 94: debugFree(extra->sigs);
95: }
1.61 daniel 96: debugFree(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");
231: rpm->extra->sigs[sign]->resolve = debugMalloc(sizeof(char) * rsize);
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;
237: rpm->extra->sigs[sign]->resolve = debugRealloc(rpm->extra->sigs[sign]->resolve,
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 */
281: sigfile = debugMalloc(30);
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);
303: debugFree(sigfile);
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.61 daniel 336: buffer = (char *) debugMalloc(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.61 daniel 392: rpm = (rpmDataPtr) debugMalloc(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.61 daniel 399: rpm->extra = (rpmExtraDataPtr) debugMalloc(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.61 daniel 424: rpm->summary = debugStrdup(localizedStrings[LANG_NO_SUMMARY]);
1.2 veillard 425: } else {
1.61 daniel 426: rpm->summary = debugStrdup((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.61 daniel 431: rpm->extra->description = debugStrdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.2 veillard 432: } else {
1.61 daniel 433: rpm->extra->description = debugStrdup((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)
524: debugFree(rpm->summary);
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.61 daniel 535: debugFree(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.61 daniel 540: rpm->extra->host = debugStrdup(localizedStrings[LANG_NO_HOST]);
1.2 veillard 541: } else {
1.61 daniel 542: rpm->extra->host = debugStrdup((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.61 daniel 568: rpm->extra->srcrpm = debugStrdup("");
1.2 veillard 569: } else {
1.61 daniel 570: rpm->extra->srcrpm = debugStrdup((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.61 daniel 577: rpm->url = debugStrdup((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.61 daniel 584: rpm->extra->packager = debugStrdup((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.61 daniel 591: rpm->extra->copyright = debugStrdup((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.61 daniel 615: buffer = (char *) debugRealloc(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.61 daniel 640: rpm->extra->changelog = debugStrdup(buffer);
1.31 veillard 641: }
1.62 daniel 642: ENTRY_CLEANUP(p);
1.7 veillard 643: if (rpm->vendor == NULL) {
1.61 daniel 644: if (rpm->extra->packager != NULL) rpm->vendor = debugStrdup(rpm->extra->packager);
645: else rpm->vendor = debugStrdup(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;
654: rpm->extra->sigs = (rpmSigPtr *) debugMalloc(sizeof(rpmSigPtr) *
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;
667: rpm->extra->sigs = (rpmSigPtr *) debugRealloc(rpm->extra->sigs,
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:
676: rpm->extra->sigs[rpm->extra->nb_sigs] = (rpmSigPtr) debugMalloc(sizeof(rpmSig));
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.86 veillard 680: rpm->extra->sigs[rpm->extra->nb_sigs]->sig = debugMalloc(count);
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.61 daniel 690: rpm->filename = debugStrdup(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.61 daniel 697: rpm->extra->resources = (rpmRessPtr *) debugMalloc(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.61 daniel 706: rpm->extra->resources = (rpmRessPtr *) debugMalloc(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.58 daniel 717: rpm->extra->resources[j++] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4 veillard 718: }
1.58 daniel 719: rpm->extra->nb_resources = j;
1.4 veillard 720: }
1.62 daniel 721: ENTRY_CLEANUP(p);
1.4 veillard 722:
723: val = getTagNumber("RPMTAG_REQUIRENAME");
724: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.73 daniel 725: rpm->extra->nb_requires = 0;
1.58 daniel 726: rpm->extra->requires = NULL;
1.4 veillard 727: } else {
1.73 daniel 728: int_32 count2, count3, type2, type3;
729: void * q = NULL;
730: void * r = NULL;
731: int valv, valf;
1.4 veillard 732:
1.70 daniel 733: rpm->extra->max_requires = count;
734: rpm->extra->requires = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) *
735: rpm->extra->max_requires);
736: if (rpm->extra->requires == NULL) {
737: fprintf(stderr, ": ran out of memory\n");
738: exit(1);
739: }
1.73 daniel 740: valv = getTagNumber("RPMTAG_REQUIREVERSION");
741: valf = getTagNumber("RPMTAG_REQUIREFLAGS");
742: headerGetEntry(h, valv, &type2, &q, &count2);
743: headerGetEntry(h, valf, &type3, &r, &count3);
1.70 daniel 744:
745: rpm->extra->nb_requires = 0;
746:
1.73 daniel 747: for (i = 0, j = 0; (i < count2) && (i < count3);i++) {
1.70 daniel 748: long anint = *(((long *)r)+i);
1.77 veillard 749: rpm_dep_flag flag = RPM2HTML_REQ_NONE;
1.70 daniel 750:
1.77 veillard 751: if ((anint & RPMSENSE_LESS) && (anint & RPMSENSE_EQUAL))
752: flag = RPM2HTML_REQ_LEQ;
753: else if (anint & RPMSENSE_LESS)
754: flag = RPM2HTML_REQ_LT;
755: if ((anint & RPMSENSE_GREATER) && (anint & RPMSENSE_EQUAL))
756: flag = RPM2HTML_REQ_GEQ;
757: else if (anint & RPMSENSE_GREATER)
758: flag = RPM2HTML_REQ_GT;
759: else if (anint & RPMSENSE_EQUAL)
760: flag = RPM2HTML_REQ_EQU;
1.53 veillard 761: if (!checkResourceName(((char **) p)[i])) continue;
1.70 daniel 762: rpm->extra->requires[j++] =
763: rpmRequAdd(((char **) p)[i],((char **) q)[i],
1.77 veillard 764: flag , rpm, installed);
1.1 veillard 765: }
1.58 daniel 766: rpm->extra->nb_requires = j;
1.73 daniel 767: if ((type2 == RPM_STRING_ARRAY_TYPE || type2 == RPM_I18NSTRING_TYPE)&&
768: (q != NULL)) { free((q)); q = NULL; }
769: if ((type3 == RPM_STRING_ARRAY_TYPE || type3 == RPM_I18NSTRING_TYPE)&&
770: (r != NULL)) { free((r)); r = NULL; }
771: for (;i < count;i++)
1.77 veillard 772: rpmRequAdd(((char **) p)[i], NULL, RPM2HTML_REQ_NONE,
773: rpm, installed);
1.5 veillard 774: }
1.62 daniel 775: ENTRY_CLEANUP(p);
1.69 daniel 776:
777: #if defined(RPMTAG_FILENAMES)
1.5 veillard 778: val = getTagNumber("RPMTAG_FILENAMES");
1.69 daniel 779: headerGetEntry(h, val, &type, &p, &count);
780: #else
781: rpmBuildFileList(h, (const char ***) &p, &count);
782: #endif
783:
784: if (count == 0) {
1.58 daniel 785: rpm->extra->filelist = NULL; /* No filelist in the package ! */
1.5 veillard 786: } else {
787: char *ptr = buffer;
1.42 veillard 788:
1.5 veillard 789: for (i = 0; i < count;i++) {
1.42 veillard 790: if ((ptr - buffer) > (buffer_size - 1024)) {
791: int delta = ptr - buffer;
792:
1.41 veillard 793: buffer_size *= 2;
1.61 daniel 794: buffer = (char *) debugRealloc(buffer, buffer_size);
1.42 veillard 795: if (buffer == NULL) {
796: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
797: buffer_size, strerror(errno));
798: exit(1);
799: }
800: ptr = &buffer[delta];
1.41 veillard 801: }
1.66 daniel 802: ptr += snprintf(ptr, buffer_size, "%s\n", ((char **) p)[i]);
1.5 veillard 803: }
1.61 daniel 804: rpm->extra->filelist = debugStrdup(buffer);
1.1 veillard 805: }
1.62 daniel 806: ENTRY_CLEANUP(p);
1.1 veillard 807:
1.86 veillard 808: #ifdef WITH_GPG
809: rpmResolveSignatures(path, nameRpm, sigtarget, rpm);
810: #endif WITH_GPG
811:
1.75 veillard 812: #ifdef WITH_SQL
813: id = sql_add_package(path, rpm->name, rpm->version, rpm->release,
814: rpm->arch, dir->no, rpm->url, rpm->extra->srcrpm,
815: dir->vendor, rpm->extra->packager,
816: rpm->group, rpm->summary, rpm->extra->description,
1.90 veillard 817: rpm->extra->copyright, rpm->date, rpm->size, rpm->os,
1.91 ! veillard 818: rpm->distribution, rpm->vendor);
1.76 veillard 819: if (id > 0) {
820: for (i = 0;i < rpm->extra->nb_resources;i++)
821: sql_add_provides(id, rpm->extra->resources[i]->name);
822: for (i = 0;i < rpm->extra->nb_requires;i++)
823: sql_add_requires(id, rpm->extra->requires[i]->name,
1.77 veillard 824: rpm->extra->requires[i]->flag,
1.76 veillard 825: rpm->extra->requires[i]->version);
826: }
1.75 veillard 827: #endif
828:
1.37 veillard 829: /* Add the package files to the real filesystem tree if asked for */
1.75 veillard 830: #ifdef WITH_SQL
831: if ((rpm->extra->filelist != NULL) &&
832: ((dir->build_tree != 0) || (id > 0))) {
833: #else
1.58 daniel 834: if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
1.75 veillard 835: #endif
1.37 veillard 836: char *cur, *filename;
837:
1.58 daniel 838: cur = rpm->extra->filelist;
1.37 veillard 839: while ((*cur != '\0') && (*cur != '/')) cur++;
840: filename = cur;
841: while (*cur != '\0') {
842: if ((*cur == '\n') || (*cur == '\r')) {
1.75 veillard 843: if (cur != filename) {
844: #ifdef WITH_SQL
845: if (dir->build_tree != 0)
846: rpmAddRealFile(dir->root, filename, rpm);
847: if (id > 0) {
848: *cur = 0;
849: sql_add_file(filename,id);
850: *cur = '\n';
851: }
852: #else
1.37 veillard 853: rpmAddRealFile(dir->root, filename, rpm);
1.75 veillard 854: #endif
855: }
1.37 veillard 856: while ((*cur != '\0') && (*cur != '/')) cur++;
857: filename = cur;
858: } else
859: cur++;
860: }
861: if (cur != filename)
862: rpmAddRealFile(dir->root, filename, rpm);
863: }
1.17 veillard 864:
865: /* Register this package */
866: rpmAddSoftware(rpm);
1.7 veillard 867:
868: /* dump the HTML related to this package */
1.56 daniel 869: if ((rpm2html_dump_html) && (dir->html))
1.40 httpng 870: dumpRpmHtml(rpm, tree);
871: if (rpm2html_dump_rdf)
872: dumpRpmRdf(rpm, tree);
1.7 veillard 873:
1.58 daniel 874: /* free the extra data */
875: rpmFreeExtraData(rpm);
1.8 veillard 876:
877: /* increment the counters */
1.11 veillard 878: if (installed) {
879: rpm2html_install_files++;
1.21 veillard 880: rpm2html_install_size += rpm->size / 1024;
1.11 veillard 881: } else {
882: rpm2html_files++;
1.21 veillard 883: rpm2html_size += rpm->size / 1024;
1.11 veillard 884: }
1.7 veillard 885:
1.32 veillard 886: return(rpm);
1.11 veillard 887: }
888:
889: /*
890: * rpmOpen : open an RPM file, read and parse the header and
891: * fill the informations in the database.
892: */
1.35 veillard 893: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32 veillard 894: rpmDataPtr cur;
1.64 daniel 895: #if defined(HAVE_RPM_RPMIO_H)
896: FD_t fd;
897: #else
1.11 veillard 898: int fd;
1.64 daniel 899: #define fdOpen(_a, _b, _c) open((_a), (_b))
900: #define fdClose(_a) close(_a)
901: #endif
1.11 veillard 902: int rc;
903: Header h = NULL;
1.83 veillard 904: Header s = NULL;
905: struct rpmlead lead;
1.11 veillard 906: int isSource;
907: char buffer[500];
1.20 veillard 908: struct stat buf;
1.86 veillard 909: #if defined(WITH_GPG)
910: FD_t ofd = NULL;
911: char *sigtarget = NULL;
912: ssize_t count;
913: unsigned char stbuffer[8192];
914: #endif
1.11 veillard 915:
916: /* open the file for reading */
1.35 veillard 917: if (tree->htmlpath[0] != '\0')
1.66 daniel 918: snprintf(buffer, sizeof(buffer), "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24 veillard 919: else
1.66 daniel 920: snprintf(buffer, sizeof(buffer), "%s/%s", dir->rpmdir, nameRpm);
1.72 daniel 921:
1.78 daniel 922: if (access(buffer, R_OK) < 0) {
923: fprintf(stderr, "open of %s failed: %s\n", buffer,
924: strerror(errno));
925: return(NULL);
926: }
1.72 daniel 927: #if defined(USE_RPMIO)
928: fd = Fopen(buffer, "r.fdio");
929: if (fd == NULL || Ferror(fd)) {
930: fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
931: Fstrerror(fd));
932: return(NULL);
933: }
934: #else
1.64 daniel 935: if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
1.11 veillard 936: fprintf(stderr, "open of %s failed: %s\n", buffer,
937: strerror(errno));
1.32 veillard 938: return(NULL);
1.11 veillard 939: }
1.72 daniel 940: #endif
1.11 veillard 941:
1.20 veillard 942: stat(buffer, &buf);
943:
1.11 veillard 944: /* read the RPM header */
945: rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
946: switch (rc) {
947: case 0:
948: if (!h) {
949: fprintf(stderr,
950: "old format source packages cannot be queried\n");
1.68 veillard 951: fdClose(fd);
1.32 veillard 952: return(NULL);
1.11 veillard 953: }
954: break;
955: case 1:
956: fprintf(stderr, "%s does not appear to be a RPM package\n",
957: nameRpm);
1.68 veillard 958: fdClose(fd);
1.32 veillard 959: return(NULL);
1.11 veillard 960: case 2:
961: fprintf(stderr, "query of %s failed\n", nameRpm);
1.68 veillard 962: fdClose(fd);
1.32 veillard 963: return(NULL);
1.11 veillard 964: default:
965: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
966: nameRpm, rc);
1.68 veillard 967: fdClose(fd);
1.32 veillard 968: return(NULL);
1.11 veillard 969: }
970:
971:
1.83 veillard 972: /* close the descriptor */
973: #if defined(USE_RPMIO)
974: Fclose(fd);
975: #else
976: fdClose(fd);
977: #endif
978:
979: /* XXX I do not know whether it is necessary to open the file twice */
980: /* open the file for reading */
981: #if defined(USE_RPMIO)
982: fd = Fopen(buffer, "r.fdio");
983: if (fd == NULL || Ferror(fd)) {
984: fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
985: Fstrerror(fd));
986: return(NULL);
987: }
988: #else
989: if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
990: fprintf(stderr, "open of %s failed: %s\n", buffer,
991: strerror(errno));
992: return(NULL);
993: }
994: #endif
995:
996: /* read the RPM signature */
997: if (readLead(fd, &lead)) {
998: fprintf(stderr, "readLead failed\n");
999: fdClose(fd);
1000: return(NULL);
1001: }
1002: switch (lead.major) {
1003: case 1:
1004: fprintf(stderr, "no signature available (v1.0 RPM) in %s\n", nameRpm);
1005: break;
1006: default:
1007: if (rpmReadSignature(fd, &s, lead.signature_type)) {
1008: fprintf(stderr, "rpmReadSignature failed\n");
1009: fdClose(fd);
1010: return(NULL);
1011: }
1012: if (!s) {
1013: fprintf(stderr, "no signature available in %s\n", nameRpm);
1014: fdClose(fd);
1015: return(NULL);
1016: }
1.86 veillard 1017: #if defined(WITH_GPG)
1018: /* open temp file for writing */
1019: sigtarget = debugMalloc(30);
1020: strcpy(sigtarget, "/tmp/rpm2html.date.XXXXXX");
1021: sigtarget = mktemp(sigtarget);
1022: ofd = Fopen(sigtarget, "w.ufdio");
1023: if (ofd == NULL || Ferror(ofd)) {
1024: fprintf(stderr, "Fopen of %s failed: %s\n", sigtarget,
1025: Fstrerror(ofd));
1026: debugFree(sigtarget);
1027: sigtarget = NULL;
1028: }
1029:
1030: /* write the header and archive to a temp file */
1031: while ((count = Fread(stbuffer, sizeof(stbuffer[0]), sizeof(stbuffer), fd)) > 0) {
1032: if (Fwrite(stbuffer, sizeof(stbuffer[0]), count, ofd) < 0) {
1033: fprintf(stderr, "%s: Fwrite failed: %s\n", sigtarget,
1034: Fstrerror(ofd));
1035: debugFree(sigtarget);
1036: sigtarget = NULL;
1037: }
1038: }
1039: if (count < 0) {
1040: fprintf(stderr, "%s: Fread failed: %s\n", buffer, Fstrerror(fd));
1041: debugFree(sigtarget);
1042: sigtarget = NULL;
1043: }
1044:
1045: Fclose(ofd);
1046: #endif
1.83 veillard 1047: break;
1048: }
1049:
1050: /* close the descriptor */
1.72 daniel 1051: #if defined(USE_RPMIO)
1052: Fclose(fd);
1053: #else
1.64 daniel 1054: fdClose(fd);
1.72 daniel 1055: #endif
1.1 veillard 1056:
1.86 veillard 1057: #if defined(WITH_GPG)
1058: cur = rpmAnalyze(buffer, nameRpm, sigtarget, h, s, dir, tree, buf.st_mtime, isSource);
1059: #else
1060: cur = rpmAnalyze(buffer, nameRpm, NULL, h, s, dir, tree, buf.st_mtime, isSource);
1061: #endif
1.83 veillard 1062:
1063: /* free the header */
1064: headerFree(h);
1065: headerFree(s);
1066:
1.86 veillard 1067: #if defined(WITH_GPG)
1068: if (sigtarget) {
1069: unlink(sigtarget);
1070: debugFree(sigtarget);
1071: }
1072: #endif
1073:
1.32 veillard 1074: return(cur);
1.6 veillard 1075: }
1076:
1077: /*
1.22 veillard 1078: * Scan one directory for RPM files this is where the recursive handling
1079: * is done.
1.6 veillard 1080: */
1.35 veillard 1081: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1082: rpmSubdirPtr subtree;
1.32 veillard 1083: rpmDataPtr ret = NULL, cur;
1.7 veillard 1084: char *filename;
1.22 veillard 1085: static char path[2000];
1.23 veillard 1086: struct stat buf;
1.7 veillard 1087: int len;
1.39 veillard 1088: DIR *d;
1089: struct dirent *file;
1.6 veillard 1090:
1.24 veillard 1091:
1092: /*
1093: * Create the directory for the HTML pages
1094: */
1.56 daniel 1095: if ((rpm2html_dump_html) && (dir->html)) {
1.45 veillard 1096: if (tree->htmlpath[0] != '\0')
1.66 daniel 1097: snprintf(path, sizeof(path), "%s/%s", dir->dir, tree->htmlpath);
1.45 veillard 1098: else
1.66 daniel 1099: snprintf(path, sizeof(path), "%s", dir->dir);
1.45 veillard 1100: createDirectory(path);
1101: }
1.43 veillard 1102:
1103: /*
1104: * Create the directory for the RDF pages
1105: if (rpm2html_rdf_dir != NULL) {
1106: if (tree->htmlpath[0] != '\0')
1.66 daniel 1107: snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
1.43 veillard 1108: else
1.66 daniel 1109: snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.43 veillard 1110: createDirectory(path);
1111: }
1.47 veillard 1112: */
1.24 veillard 1113:
1114: /*
1115: * Scan the repository.
1116: */
1.35 veillard 1117: if (tree->rpmpath[0] != '\0')
1.66 daniel 1118: snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, tree->rpmpath);
1.24 veillard 1119: else
1.66 daniel 1120: snprintf(path, sizeof(path), "%s", dir->rpmdir);
1.51 veillard 1121: if (rpm2htmlVerbose > 1)
1.66 daniel 1122: printf("Scanning directory %s\n", path);
1.24 veillard 1123:
1.39 veillard 1124: d = opendir(path);
1125: if (d == NULL) {
1.24 veillard 1126: fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6 veillard 1127: strerror(errno));
1.35 veillard 1128: rpmRemoveSubdir(tree);
1.36 veillard 1129: rpmFreeSubdir(tree);
1.32 veillard 1130: return(NULL);
1.6 veillard 1131: } else {
1.39 veillard 1132: while ((file = readdir(d)) != NULL) {
1.32 veillard 1133: cur = NULL;
1.39 veillard 1134: filename = file->d_name;
1.7 veillard 1135: len = strlen(filename);
1.24 veillard 1136:
1137: /*
1138: * Compute the full path
1139: */
1.35 veillard 1140: if (tree->rpmpath[0] != '\0')
1.66 daniel 1141: snprintf(path, sizeof(path), "%s/%s/%s", dir->rpmdir, tree->rpmpath,
1.35 veillard 1142: filename);
1.22 veillard 1143: else
1.66 daniel 1144: snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, filename);
1.22 veillard 1145:
1146: /*
1.25 veillard 1147: * Stat() the file to detect directory and symlimks
1148: */
1.30 veillard 1149: if (lstat(path, &buf) != 0) {
1.25 veillard 1150: fprintf(stderr, "Couldn't stat(%s)\n", path);
1151: continue;
1152: }
1.35 veillard 1153:
1.25 veillard 1154: /*
1.23 veillard 1155: * Check for RPM files by looking at the suffix
1.54 veillard 1156: * Note that SuSE source RPMs have a ".spm" suffix
1.63 daniel 1157: * We may or may not follow symlinks to RPM files
1.22 veillard 1158: */
1.63 daniel 1159: if (((len >= 5) &&
1.54 veillard 1160: (!strcasecmp(&filename[len - 4], ".rpm"))) ||
1161: ((len >= 5) &&
1162: (!strcasecmp(&filename[len - 4], ".spm")))) {
1.63 daniel 1163:
1.65 daniel 1164: if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) {
1.66 daniel 1165: if (rpm2htmlVerbose > 1)
1.63 daniel 1166: fprintf(stderr, "Dropping symlink %s\n", path);
1167: continue;
1168: }
1.35 veillard 1169: cur = rpmOpen(filename, dir, tree);
1.63 daniel 1170: }
1171:
1172: /*
1173: * Don't follow of analyze symlinks,
1174: */
1.65 daniel 1175: else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0)) {
1.66 daniel 1176: if (rpm2htmlVerbose > 1)
1.63 daniel 1177: fprintf(stderr, "Dropping symlink %s\n", path);
1178: continue;
1.44 veillard 1179: }
1180:
1181: /*
1182: * Check for RDF files by looking at the suffix
1183: */
1184: else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
1185: cur = rpmOpenRdf(filename, dir, tree);
1.22 veillard 1186: }
1.35 veillard 1187:
1.22 veillard 1188: /*
1.23 veillard 1189: * Else if this is a directory, recurse !
1.22 veillard 1190: */
1.25 veillard 1191: else if (S_ISDIR(buf.st_mode)) {
1192: if (filename[0] != '.') {
1.57 daniel 1193: subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
1.35 veillard 1194: cur = rpmOneDirScan(dir, subtree);
1.25 veillard 1195: }
1.22 veillard 1196: }
1.32 veillard 1197: if (cur != NULL) ret = rpmAddList(ret, cur);
1.7 veillard 1198: }
1.6 veillard 1199: }
1.39 veillard 1200: closedir(d);
1.33 veillard 1201:
1202: /*
1203: * Dump the pages related to this directory.
1204: */
1.35 veillard 1205: if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36 veillard 1206: else {
1207: rpmRemoveSubdir(tree);
1208: rpmFreeSubdir(tree);
1209: }
1.35 veillard 1210:
1.32 veillard 1211: return(ret);
1.22 veillard 1212: }
1213:
1214: /*
1215: * Scan a directory for RPM files.
1216: */
1.35 veillard 1217: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37 veillard 1218: rpmSubdirPtr cur;
1219: rpmDataPtr ret;
1220:
1.56 daniel 1221: if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
1.37 veillard 1222: dir->root = rpmCreateRealRoot();
1223: }
1224: cur = rpmNewSubdir(tree, dir->name,
1.57 daniel 1225: dir->subdir == NULL ? "" : dir->subdir, "", dir->color,
1226: dir->html);
1.37 veillard 1227: ret = rpmOneDirScan(dir, cur);
1.38 veillard 1228: rpmDumpHtmlRealRoot(dir);
1.37 veillard 1229: return(ret);
1.6 veillard 1230: }
1231:
1232: /*
1.11 veillard 1233: * Scan the local RPM database for RPM files.
1234: */
1.32 veillard 1235: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37 veillard 1236: static char path[2000];
1.32 veillard 1237: rpmDataPtr ret = NULL, cur;
1.11 veillard 1238: rpmdb db;
1239: Header h = NULL;
1.72 daniel 1240: #ifndef USE_RPMIO
1.32 veillard 1241: int offset;
1.71 daniel 1242: #endif
1.11 veillard 1243: char *prefix = "/";
1.88 veillard 1244:
1245: #ifdef WITH_SQL
1246: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1247: #endif
1.11 veillard 1248:
1.37 veillard 1249: /*
1250: * Create the directory for the HTML pages
1251: */
1.56 daniel 1252: if ((rpm2html_dump_html) && (dir->html)) {
1.45 veillard 1253: if (dir->subdir)
1.66 daniel 1254: snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir);
1.45 veillard 1255: else
1.66 daniel 1256: snprintf(path, sizeof(path), "%s", dir->dir);
1.45 veillard 1257: createDirectory(path);
1258: }
1259:
1260: /*
1261: * Create the directory for the RDF pages
1262: */
1263: if (rpm2html_rdf_dir != NULL) {
1264: if (dir->subdir)
1.66 daniel 1265: snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, dir->subdir);
1.45 veillard 1266: else
1.66 daniel 1267: snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.45 veillard 1268: createDirectory(path);
1269: }
1.37 veillard 1270:
1.66 daniel 1271: if (rpm2htmlVerbose)
1272: printf("Scanning the database of installed RPMs\n");
1.70 daniel 1273:
1274: if (dir->dbpath != NULL)
1275: addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7); /* Added by A.Gibert */
1.66 daniel 1276:
1.11 veillard 1277: if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32 veillard 1278: return(NULL);
1.11 veillard 1279: }
1.71 daniel 1280:
1.72 daniel 1281: #ifdef USE_RPMIO
1.71 daniel 1282: { rpmdbMatchIterator mi;
1283: mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
1284: while ((h = rpmdbNextIterator(mi)) != NULL) {
1.86 veillard 1285: cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.71 daniel 1286: if (cur != NULL) ret = rpmAddList(ret, cur);
1287: }
1288: rpmdbFreeIterator(mi);
1289: }
1.72 daniel 1290: #else /* USE_RPMIO */
1.11 veillard 1291: offset = rpmdbFirstRecNum(db);
1292: while (offset) {
1293: h = rpmdbGetRecord(db, offset);
1294: if (!h) {
1295: fprintf(stderr, "could not read database record!\n");
1.32 veillard 1296: return(ret);
1.11 veillard 1297: }
1.86 veillard 1298: cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.32 veillard 1299: if (cur != NULL) ret = rpmAddList(ret, cur);
1.11 veillard 1300: headerFree(h);
1301: offset = rpmdbNextRecNum(db, offset);
1302: }
1.72 daniel 1303: #endif /* USE_RPMIO */
1.71 daniel 1304:
1.11 veillard 1305: rpmdbClose(db);
1306:
1.32 veillard 1307: return(ret);
1.80 veillard 1308: }
1309:
1310:
1311: /*
1312: * Scan one distribution only
1313: */
1314:
1315: void rpmDirScanOneDist(const char *dist) {
1316: rpmDirPtr dir;
1317: rpmDataPtr cur;
1318:
1319: /*
1320: * first try to find the distrib
1321: */
1322: dir = dirList;
1323: while (dir != NULL) {
1324: if (!strcasecmp(dir->name, dist))
1325: break;
1326: if (!strcasecmp(dir->subdir, dist))
1327: break;
1328: if (!strcasecmp(dir->rpmdir, dist))
1329: break;
1330: dir = dir->next;
1331: }
1332: if (dir == NULL) {
1333: dir = dirList;
1334: while (dir != NULL) {
1335: if (!strstr(dir->name, dist))
1336: break;
1337: if (!strstr(dir->subdir, dist))
1338: break;
1339: if (!strstr(dir->rpmdir, dist))
1340: break;
1341: dir = dir->next;
1342: }
1343: }
1344: if (dir == NULL) {
1345: fprintf(stderr, "rpmDirScanOneDist(%s): distribution not found\n",
1346: dist);
1347: return;
1348: }
1349: if (rpm2htmlVerbose)
1350: printf("indexing %s\n", dir->name);
1351:
1352: /*
1353: * Allocate a directory tree.
1354: */
1355: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1356:
1357: cur = NULL;
1358:
1359: /*
1360: * Override default setting.
1361: */
1362: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1363: dir->maint = debugStrdup(rpm2html_maint);
1364: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1365: dir->mail = debugStrdup(rpm2html_mail);
1366: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1367: dir->ftp = debugStrdup(rpm2html_ftp);
1368: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1369: dir->ftpsrc = debugStrdup(rpm2html_ftpsrc);
1370: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1371: dir->dir = debugStrdup(rpm2html_dir);
1372: if ((dir->host == NULL) && (rpm2html_host != NULL))
1373: dir->host = debugStrdup(rpm2html_host);
1374: if ((dir->name == NULL) && (rpm2html_name != NULL))
1375: dir->name = debugStrdup(rpm2html_name);
1376: if ((dir->url == NULL) && (rpm2html_url != NULL))
1377: dir->url = debugStrdup(rpm2html_url);
1378:
1379: if (dir->rpmdir == NULL) {
1380: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1381: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1382: /* Scan the local RPM database instead of a directory */
1383: cur = rpmBaseScan(dir);
1384: } else if (dir->ftp == NULL) {
1385: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1386: dir->rpmdir);
1387: } else {
1.82 veillard 1388: #ifdef WITH_SQL
1.80 veillard 1389: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82 veillard 1390: #endif
1.80 veillard 1391: if (rpm2htmlVerbose)
1392: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1393: cur = rpmDirScan(dir, dirTree);
1394: }
1395:
1396: if (dir->root != NULL) {
1397: rpmDestroyRealRoot(dir->root);
1398: dir->root = NULL;
1399: }
1.11 veillard 1400: }
1401:
1402: /*
1.6 veillard 1403: * Scan all registered directories.
1404: * One fist check for completeness of the informations in
1405: * the rpmDir structure.
1406: */
1407:
1.32 veillard 1408: rpmDataPtr rpmDirScanAll(void) {
1.18 veillard 1409: rpmDirPtr dir, next;
1.32 veillard 1410: rpmDataPtr ret = NULL, cur;
1.91 ! veillard 1411: #ifndef WITH_SQL
1.46 veillard 1412: int maxLists = 50;
1413: rpmDataPtr *rpmLists;
1.35 veillard 1414: int nbLists = 0;
1415: int i;
1.91 ! veillard 1416: #endif
1.18 veillard 1417:
1418: /*
1419: * first reverse the list ....
1420: */
1421: dir = dirList;
1422: dirList = NULL;
1423: while (dir != NULL) {
1424: next = dir->next;
1425: dir->next = dirList;
1426: dirList = dir;
1427: dir = next;
1428: }
1.57 daniel 1429: dir = dirList;
1.18 veillard 1430:
1.35 veillard 1431: /*
1432: * Allocate a directory tree.
1433: */
1.57 daniel 1434: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1.6 veillard 1435:
1.91 ! veillard 1436: #ifndef WITH_SQL
1.61 daniel 1437: rpmLists = (rpmDataPtr *) debugMalloc(maxLists * sizeof(rpmDataPtr));
1.46 veillard 1438: if (rpmLists == NULL) {
1439: fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
1440: exit(1);
1441: }
1.91 ! veillard 1442: #endif
1.46 veillard 1443:
1.6 veillard 1444: while (dir != NULL) {
1.32 veillard 1445: cur = NULL;
1446:
1.14 veillard 1447: /*
1.91 ! veillard 1448: * Complete with default setting.
1.14 veillard 1449: */
1.15 veillard 1450: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.61 daniel 1451: dir->maint = debugStrdup(rpm2html_maint);
1.15 veillard 1452: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.61 daniel 1453: dir->mail = debugStrdup(rpm2html_mail);
1.15 veillard 1454: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.61 daniel 1455: dir->ftp = debugStrdup(rpm2html_ftp);
1.15 veillard 1456: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.61 daniel 1457: dir->ftpsrc = debugStrdup(rpm2html_ftpsrc);
1.15 veillard 1458: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.61 daniel 1459: dir->dir = debugStrdup(rpm2html_dir);
1.15 veillard 1460: if ((dir->host == NULL) && (rpm2html_host != NULL))
1.61 daniel 1461: dir->host = debugStrdup(rpm2html_host);
1.15 veillard 1462: if ((dir->name == NULL) && (rpm2html_name != NULL))
1.61 daniel 1463: dir->name = debugStrdup(rpm2html_name);
1.15 veillard 1464: if ((dir->url == NULL) && (rpm2html_url != NULL))
1.61 daniel 1465: dir->url = debugStrdup(rpm2html_url);
1.14 veillard 1466:
1467: if (dir->rpmdir == NULL) {
1.6 veillard 1468: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.91 ! veillard 1469: } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1.11 veillard 1470: /* Scan the local RPM database instead of a directory */
1.32 veillard 1471: cur = rpmBaseScan(dir);
1.7 veillard 1472: } else if (dir->ftp == NULL) {
1473: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14 veillard 1474: dir->rpmdir);
1.6 veillard 1475: } else {
1.82 veillard 1476: #ifdef WITH_SQL
1.79 veillard 1477: dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82 veillard 1478: #endif
1.51 veillard 1479: if (rpm2htmlVerbose)
1.66 daniel 1480: printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1.35 veillard 1481: cur = rpmDirScan(dir, dirTree);
1.6 veillard 1482: }
1483:
1.91 ! veillard 1484: #ifdef WITH_SQL
! 1485: /*
! 1486: * The packages list will be reextratced from the
! 1487: * database at the end, minimize memory consumption
! 1488: */
! 1489: rpmlistCleanup();
! 1490: #else
1.35 veillard 1491: if (cur != NULL) {
1.46 veillard 1492: if (nbLists >= maxLists) {
1493: maxLists *= 2;
1.61 daniel 1494: rpmLists = (rpmDataPtr *) debugRealloc(rpmLists,
1.46 veillard 1495: maxLists * sizeof(rpmDataPtr));
1496: if (rpmLists == NULL) {
1497: fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
1498: exit(1);
1.35 veillard 1499: }
1500: }
1.46 veillard 1501: rpmLists[nbLists] = cur;
1502: nbLists++;
1.39 veillard 1503: }
1.91 ! veillard 1504: #endif
1.39 veillard 1505: if (dir->root != NULL) {
1.48 veillard 1506: rpmDestroyRealRoot(dir->root);
1507: dir->root = NULL;
1.35 veillard 1508: }
1.6 veillard 1509: dir = dir->next;
1510: }
1.91 ! veillard 1511: #ifndef WITH_SQL
1.35 veillard 1512: for (i = 0;i < nbLists;i++)
1513: ret = rpmAddList(ret, rpmLists[i]);
1.61 daniel 1514: debugFree(rpmLists);
1.91 ! veillard 1515: #endif
1.32 veillard 1516: return(ret);
1.60 daniel 1517: }
1518:
1519: /*
1520: * Cleanup the global variables from this module
1521: */
1522: void rpmopenCleanup(void) {
1523: if (buffer != NULL)
1.61 daniel 1524: debugFree(buffer);
1.60 daniel 1525: buffer = NULL;
1526: buffer_size = 50 * 1024 * sizeof(char);
1.1 veillard 1527: }
1528:
Webmaster