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