Annotation of rpm2html/rpmopen.c, revision 1.65
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.65 ! daniel 6: * $Id: rpmopen.c,v 1.64 1999/04/08 10:08:52 daniel Exp $
1.1 veillard 7: */
8:
1.9 veillard 9: #include <config.h>
1.1 veillard 10: #include <sys/types.h>
11: #include <sys/stat.h>
1.9 veillard 12: #ifdef HAVE_FCNTL_H
1.1 veillard 13: #include <fcntl.h>
1.9 veillard 14: #endif
1.1 veillard 15: #include <stdio.h>
16: #include <stdlib.h>
17: #include <string.h>
1.9 veillard 18: #ifdef HAVE_UNISTD_H
1.1 veillard 19: #include <unistd.h>
1.9 veillard 20: #endif
1.6 veillard 21: #include <dirent.h>
1.13 veillard 22: #include <errno.h>
1.31 veillard 23: #include <time.h>
1.1 veillard 24:
25: #include <rpm/rpmlib.h>
26:
27: #include "rpmdata.h"
1.7 veillard 28: #include "html.h"
1.40 httpng 29: #include "rdf.h"
1.8 veillard 30: #include "rpm2html.h"
1.12 veillard 31: #include "language.h"
1.1 veillard 32:
33: /*
34: * Get the internal number associated to an RPM tag.
35: */
36: static int getTagNumber(char *tag) {
37: int i;
38: const struct headerTagTableEntry * t;
39:
40: for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
41: if (!strcasecmp(tag, t->name)) return(t->val);
42: }
43: fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
44: return(-1);
45: }
46:
47: /*
1.58 daniel 48: * Free up the extra data not needed for the last stage processing.
49: */
50:
51: void rpmFreeExtraData(rpmDataPtr rpm) {
52: rpmExtraDataPtr extra;
53:
54: if ((rpm == NULL) || (rpm->extra == NULL)) return;
55: extra = rpm->extra;
1.61 daniel 56: if (extra->packager != NULL) debugFree(extra->packager);
57: if (extra->description != NULL) debugFree(extra->description);
58: if (extra->copyright != NULL) debugFree(extra->copyright);
59: if (extra->changelog != NULL) debugFree(extra->changelog);
60: if (extra->srcrpm != NULL) debugFree(extra->srcrpm);
61: if (extra->host != NULL) debugFree(extra->host);
62: if (extra->resources != NULL) debugFree(extra->resources);
63: if (extra->requires != NULL) debugFree(extra->requires);
64: if (extra->filelist != NULL) debugFree(extra->filelist);
65: debugFree(extra);
1.58 daniel 66: }
67:
68: /*
1.59 daniel 69: * check a dependancy name to get rid of bad deps due to bad scripts
1.55 daniel 70: * or spec files.
1.53 veillard 71: */
72: int checkResourceName(const char *res) {
1.59 daniel 73: int isname = 0;
74: const char *base = res;
1.55 daniel 75:
1.53 veillard 76: if (*res == 0) return(0);
1.55 daniel 77:
78: /*
1.59 daniel 79: * we only accept absolute pathnames.
1.55 daniel 80: */
1.59 daniel 81: if (*res == '/') isname = 1;
1.53 veillard 82: while (*res != 0) {
1.59 daniel 83: if (((*res >= 'A') && (*res <= 'Z')) ||
84: ((*res >= 'a') && (*res <= 'z')) ||
1.53 veillard 85: ((*res >= '0') && (*res <= '9')) ||
1.55 daniel 86: (*res == '-') || (*res == '.') ||
87: (*res == '@') || (*res == '_') ||
1.59 daniel 88: (*res == '+') ||
89: ((*res == '/') && (isname == 1)))
1.53 veillard 90: res++;
91: else
92: return(0);
1.59 daniel 93: if ((res - base) > 100) return(0);
94: }
95: return(1);
96: }
97:
98: /*
99: * check a release name
100: */
101: int checkReleaseName(const char *res) {
102: const char *base = res;
103:
104: if (*res == 0) return(0);
105:
106: while (*res != 0) {
107: if (((*res >= 'A') && (*res <= 'Z')) ||
108: ((*res >= 'a') && (*res <= 'z')) ||
109: ((*res >= '0') && (*res <= '9')) ||
110: (*res == '-') || (*res == '.') ||
111: (*res == '@') || (*res == '_') ||
112: (*res == '+'))
113: res++;
114: else
115: return(0);
116: if ((res - base) > 20) return(0);
117: }
118: return(1);
119: }
120:
121: /*
122: * check a group name
123: */
124: int checkGroupName(const char *res) {
125: const char *base = res;
126:
127: /* Grrr !!! Suse packages have an empty Group name
128: if (*res == 0) return(0);
129: */
130:
131: while (*res != 0) {
132: if (((*res >= 'A') && (*res <= 'Z')) ||
133: ((*res >= 'a') && (*res <= 'z')) ||
134: ((*res >= '0') && (*res <= '9')) ||
135: (*res == ' ') || (*res == '.') ||
136: (*res == '+') || (*res == '/') ||
137: (*res == '-'))
138: res++;
139: else
140: return(0);
141: if ((res - base) > 60) return(0);
142: }
143: return(1);
144: }
145:
146: /*
147: * check a version name
148: */
149: int checkVersionName(const char *res) {
150: const char *base = res;
151:
152: if (*res == 0) return(0);
153:
154: while (*res != 0) {
155: if (((*res >= 'A') && (*res <= 'Z')) ||
156: ((*res >= 'a') && (*res <= 'z')) ||
157: ((*res >= '0') && (*res <= '9')) ||
158: (*res == '-') || (*res == '.') ||
159: (*res == '@') || (*res == '_') ||
160: (*res == '+'))
161: res++;
162: else
163: return(0);
164: if ((res - base) > 20) return(0);
1.53 veillard 165: }
166: return(1);
167: }
1.60 daniel 168:
1.53 veillard 169: /*
1.11 veillard 170: * rpmAnalyze : analyze an RPM record, read and parse the header and
171: * fill the informations in the database.
1.1 veillard 172: */
1.62 daniel 173: #define ENTRY_CLEANUP(p) \
174: if ((type == RPM_STRING_ARRAY_TYPE || type == RPM_I18NSTRING_TYPE)&&\
175: (p != NULL)) { free((p)); p = NULL; }
176:
1.60 daniel 177: static char *buffer = NULL;
178: static int buffer_size = 50 * 1024 * sizeof(char);
1.61 daniel 179:
1.36 veillard 180: rpmDataPtr rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir,
1.52 daniel 181: rpmSubdirPtr tree, time_t stamp, int isSource) {
1.11 veillard 182: int installed = dir->installbase;
1.2 veillard 183: char * name = NULL, * version = NULL, * release = NULL;
1.1 veillard 184: int_32 count, type;
1.2 veillard 185: void * p = NULL;
1.10 veillard 186: int val, i, j;
1.1 veillard 187: rpmDataPtr rpm = NULL;
1.11 veillard 188: static char nameBuffer[500];
1.1 veillard 189:
1.41 veillard 190: if (buffer == NULL) {
1.61 daniel 191: buffer = (char *) debugMalloc(buffer_size);
1.41 veillard 192: if (buffer == NULL) {
193: fprintf(stderr, "cannot allocate %d bytes: %s\n", buffer_size,
194: strerror(errno));
195: exit(1);
196: }
197: }
198:
1.1 veillard 199: /* extract informations from the header */
200: headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
1.49 veillard 201: if (name == NULL) {
202: fprintf(stderr, "Invalid package %s : no name\n", nameRpm);
203: return(NULL);
204: }
205: if (!(((name[0] >= 'a') && (name[0] <= 'z')) ||
206: ((name[0] >= 'A') && (name[0] <= 'Z')) ||
207: ((name[0] >= '0') && (name[0] <= '9')))) {
208: fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
1.62 daniel 209: ENTRY_CLEANUP(name)
1.49 veillard 210: return(NULL);
211: }
1.59 daniel 212: if (!checkResourceName(name)) {
213: fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
1.62 daniel 214: ENTRY_CLEANUP(name)
1.59 daniel 215: return(NULL);
216: }
1.1 veillard 217: headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
1.49 veillard 218: if ((version == NULL) || (version[0] == 0)) {
219: fprintf(stderr, "Invalid package %s : version invalid\n", nameRpm);
1.62 daniel 220: ENTRY_CLEANUP(name)
221: ENTRY_CLEANUP(version)
1.49 veillard 222: return(NULL);
223: }
1.59 daniel 224: if (!checkVersionName(version)) {
225: fprintf(stderr, "Invalid package %s : garbled version\n", nameRpm);
1.62 daniel 226: ENTRY_CLEANUP(name)
227: ENTRY_CLEANUP(version)
1.59 daniel 228: return(NULL);
229: }
1.1 veillard 230: headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
1.49 veillard 231: if ((release == NULL) || (release[0] == 0)) {
232: fprintf(stderr, "Invalid package %s : release invalid\n", nameRpm);
1.62 daniel 233: ENTRY_CLEANUP(name)
234: ENTRY_CLEANUP(version)
235: ENTRY_CLEANUP(release)
1.49 veillard 236: return(NULL);
237: }
1.59 daniel 238: if (!checkReleaseName(release)) {
239: fprintf(stderr, "Invalid package %s : garbled release\n", nameRpm);
1.62 daniel 240: ENTRY_CLEANUP(name)
241: ENTRY_CLEANUP(version)
242: ENTRY_CLEANUP(release)
1.59 daniel 243: return(NULL);
244: }
1.1 veillard 245:
1.58 daniel 246: /* allocate a new rpmData block, and an rpmExtraData block fill them */
1.61 daniel 247: rpm = (rpmDataPtr) debugMalloc(sizeof(rpmData));
1.1 veillard 248: if (rpm == NULL) {
1.41 veillard 249: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
250: strerror(errno));
251: return(NULL);
1.1 veillard 252: }
1.44 veillard 253: memset(rpm, 0, sizeof(rpmData));
1.61 daniel 254: rpm->extra = (rpmExtraDataPtr) debugMalloc(sizeof(rpmExtraData));
1.58 daniel 255: if (rpm == NULL) {
256: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmExtraData),
257: strerror(errno));
258: return(NULL);
259: }
260: memset(rpm->extra, 0, sizeof(rpmExtraData));
1.6 veillard 261: rpm->dir = dir;
1.36 veillard 262: if (tree) {
263: if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
1.61 daniel 264: rpm->subdir = stringAdd(tree->rpmpath);
1.36 veillard 265: else
266: rpm->subdir = NULL;
267: } else
268: rpm->subdir = NULL;
1.58 daniel 269: rpm->extra->stamp = stamp;
1.61 daniel 270: rpm->name = stringAdd(name);
1.62 daniel 271: ENTRY_CLEANUP(name)
1.61 daniel 272: rpm->version = stringAdd(version);
1.62 daniel 273: ENTRY_CLEANUP(version)
1.61 daniel 274: rpm->release = stringAdd(release);
1.62 daniel 275: ENTRY_CLEANUP(release)
1.1 veillard 276:
1.26 veillard 277: /* get all the resources provided by this RPM */
1.2 veillard 278: if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.61 daniel 279: rpm->summary = debugStrdup(localizedStrings[LANG_NO_SUMMARY]);
1.2 veillard 280: } else {
1.61 daniel 281: rpm->summary = debugStrdup((char *) p);
1.2 veillard 282: }
1.62 daniel 283: ENTRY_CLEANUP(p);
1.28 veillard 284: if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p ||
285: (type != RPM_STRING_TYPE)) {
1.61 daniel 286: rpm->extra->description = debugStrdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.2 veillard 287: } else {
1.61 daniel 288: rpm->extra->description = debugStrdup((char *) p);
1.2 veillard 289: }
1.62 daniel 290: ENTRY_CLEANUP(p);
1.28 veillard 291: if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p ||
292: (type != RPM_STRING_TYPE)) {
1.61 daniel 293: rpm->distribution = stringAdd(localizedStrings[LANG_UNKNOWN]);
1.2 veillard 294: } else {
1.61 daniel 295: rpm->distribution = stringAdd((char *) p);
1.2 veillard 296: }
1.62 daniel 297: ENTRY_CLEANUP(p);
1.52 daniel 298: if (isSource) {
1.61 daniel 299: rpm->arch = stringAdd("src");
1.11 veillard 300: if (nameRpm == NULL) {
1.52 daniel 301: sprintf(nameBuffer, "%s-%s-%s.src.rpm",
302: name, version, release);
1.11 veillard 303: nameRpm = nameBuffer;
304: }
1.2 veillard 305: } else {
1.52 daniel 306: if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p ||
307: (type != RPM_STRING_TYPE)) {
308: if (type == RPM_INT8_TYPE) {
309: /*
310: * Old packages.
311: */
312: switch (*((char *) p)) {
313: case 1:
1.61 daniel 314: rpm->arch = stringAdd("i386");
1.52 daniel 315: break;
316: default:
1.61 daniel 317: rpm->arch = stringAdd("src");
1.52 daniel 318: break;
319: }
320: } else
1.61 daniel 321: rpm->arch = stringAdd(localizedStrings[LANG_NONE]);
1.52 daniel 322: if (nameRpm == NULL) {
323: sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
324: nameRpm = nameBuffer;
325: }
326: } else {
1.61 daniel 327: rpm->arch = stringAdd((char *) p);
1.52 daniel 328: if (nameRpm == NULL) {
329: sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
330: name, version, release, (char *)p);
331: nameRpm = nameBuffer;
332: }
1.11 veillard 333: }
1.62 daniel 334: ENTRY_CLEANUP(p);
1.2 veillard 335: }
1.28 veillard 336: if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p ||
337: (type != RPM_STRING_TYPE)) {
1.29 veillard 338: if (type == RPM_INT8_TYPE) {
339: /*
1.32 veillard 340: * Old packages.
1.29 veillard 341: */
342: switch (*((char *) p)) {
343: case 1:
1.61 daniel 344: rpm->os = stringAdd("linux");
1.29 veillard 345: break;
346: default:
1.61 daniel 347: rpm->os = stringAdd("linux");
1.29 veillard 348: break;
349: }
350: } else
1.61 daniel 351: rpm->os = stringAdd("");
1.7 veillard 352: } else {
1.61 daniel 353: rpm->os = stringAdd((char *) p);
1.7 veillard 354: }
1.62 daniel 355: ENTRY_CLEANUP(p);
1.28 veillard 356: if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p ||
357: (type != RPM_STRING_TYPE)) {
1.7 veillard 358: rpm->vendor = NULL;
1.2 veillard 359: } else {
1.61 daniel 360: rpm->vendor = stringAdd((char *) p);
1.2 veillard 361: }
1.62 daniel 362: ENTRY_CLEANUP(p);
1.28 veillard 363: if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p ||
364: (type != RPM_STRING_TYPE)) {
1.61 daniel 365: rpm->group = stringAdd(localizedStrings[LANG_NO_GROUP]);
1.2 veillard 366: } else {
1.61 daniel 367: rpm->group = stringAdd((char *) p);
1.59 daniel 368: }
1.62 daniel 369: ENTRY_CLEANUP(p);
1.59 daniel 370: if (!checkGroupName(rpm->group)) {
371: fprintf(stderr, "Invalid package %s : garbled group\n", nameRpm);
1.61 daniel 372: stringFree(rpm->name);
373: stringFree(rpm->version);
374: stringFree(rpm->release);
375: debugFree(rpm->summary);
376: stringFree(rpm->distribution);
377: stringFree(rpm->arch);
378: stringFree(rpm->os);
379: stringFree(rpm->vendor);
380: stringFree(rpm->group);
381: debugFree(rpm);
1.59 daniel 382: return(NULL);
1.2 veillard 383: }
1.28 veillard 384: if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p ||
385: (type != RPM_STRING_TYPE)) {
1.61 daniel 386: rpm->extra->host = debugStrdup(localizedStrings[LANG_NO_HOST]);
1.2 veillard 387: } else {
1.61 daniel 388: rpm->extra->host = debugStrdup((char *) p);
1.2 veillard 389: }
1.62 daniel 390: ENTRY_CLEANUP(p);
1.2 veillard 391: if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
392: rpm->size = 0;
393: } else {
394: rpm->size = *((int *) p);
395: }
1.62 daniel 396: ENTRY_CLEANUP(p);
1.11 veillard 397: if (installed) {
398: if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
399: rpm->date = 0;
400: } else {
401: rpm->date = *((int_32 *) p);
402: }
1.62 daniel 403: ENTRY_CLEANUP(p);
1.2 veillard 404: } else {
1.11 veillard 405: if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
406: rpm->date = 0;
407: } else {
408: rpm->date = *((int_32 *) p);
409: }
1.62 daniel 410: ENTRY_CLEANUP(p);
1.2 veillard 411: }
1.28 veillard 412: if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p ||
413: (type != RPM_STRING_TYPE)) {
1.61 daniel 414: rpm->extra->srcrpm = debugStrdup("");
1.2 veillard 415: } else {
1.61 daniel 416: rpm->extra->srcrpm = debugStrdup((char *) p);
1.2 veillard 417: }
1.62 daniel 418: ENTRY_CLEANUP(p);
1.28 veillard 419: if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p ||
420: (type != RPM_STRING_TYPE)) {
1.7 veillard 421: rpm->url = NULL;
422: } else {
1.61 daniel 423: rpm->url = debugStrdup((char *) p);
1.7 veillard 424: }
1.62 daniel 425: ENTRY_CLEANUP(p);
1.28 veillard 426: if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p ||
427: (type != RPM_STRING_TYPE)) {
1.58 daniel 428: rpm->extra->packager = NULL;
1.7 veillard 429: } else {
1.61 daniel 430: rpm->extra->packager = debugStrdup((char *) p);
1.7 veillard 431: }
1.62 daniel 432: ENTRY_CLEANUP(p);
1.28 veillard 433: if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p ||
434: (type != RPM_STRING_TYPE)) {
1.58 daniel 435: rpm->extra->copyright = NULL;
1.7 veillard 436: } else {
1.61 daniel 437: rpm->extra->copyright = debugStrdup((char *) p);
1.7 veillard 438: }
1.62 daniel 439: ENTRY_CLEANUP(p);
1.31 veillard 440: /* Pick up changelog entries */
441: if (!headerGetEntry(h, RPMTAG_CHANGELOGTEXT, &type, &p, &count) || !p) {
1.58 daniel 442: rpm->extra->changelog = NULL;
1.31 veillard 443: } else {
444: time_t *dates;
445: char **names;
446: char **holdp = (char **)p;
447: char *cp;
448: struct tm *tm_buf;
449: int i, len, pos;
450: char date_string[50];
451: char *res = buffer;
1.42 veillard 452:
1.31 veillard 453: *res = '\0';
454: headerGetEntry(h, RPMTAG_CHANGELOGTIME, &type, (void *)&dates, &count);
455: headerGetEntry(h, RPMTAG_CHANGELOGNAME, &type, (void *)&names, &count);
456: for (i = 0; i < count; i++) {
1.42 veillard 457: if ((res - buffer) > (buffer_size - 1024)) {
458: int delta = res - buffer;
459:
1.41 veillard 460: buffer_size *= 2;
1.61 daniel 461: buffer = (char *) debugRealloc(buffer, buffer_size);
1.42 veillard 462: if (buffer == NULL) {
463: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
464: buffer_size, strerror(errno));
465: exit(1);
466: }
467: res = &buffer[delta];
1.41 veillard 468: }
1.31 veillard 469: tm_buf = localtime(&dates[i]);
470: strftime(date_string, sizeof(date_string) - 1, "%a %b %d %Y", tm_buf);
471: len = sprintf(res, "* %s %s\n", date_string, names[i]);
472: res += len;
473: cp = holdp[i];
474: pos = 0;
475: while (*cp) {
476: if (pos++ == 0) {
477: *res++ = ' ';
478: *res++ = ' ';
479: }
480: *res++ = *cp;
481: if (*cp++ == '\n') pos = 0;
482: }
483: *res++ = '\n';
484: }
485: *res = '\0';
1.61 daniel 486: rpm->extra->changelog = debugStrdup(buffer);
1.31 veillard 487: }
1.62 daniel 488: ENTRY_CLEANUP(p);
1.7 veillard 489: if (rpm->vendor == NULL) {
1.61 daniel 490: if (rpm->extra->packager != NULL) rpm->vendor = debugStrdup(rpm->extra->packager);
491: else rpm->vendor = debugStrdup(localizedStrings[LANG_UNKNOWN]);
1.7 veillard 492: }
1.2 veillard 493:
1.61 daniel 494: rpm->filename = debugStrdup(nameRpm);
1.11 veillard 495:
1.48 veillard 496: /* package-xxx.rpm provides at least the resource "package" */
1.1 veillard 497: val = getTagNumber("RPMTAG_PROVIDES");
498: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.58 daniel 499: rpm->extra->nb_resources = 1;
500: rpm->extra->max_resources = 1;
1.61 daniel 501: rpm->extra->resources = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) *
1.58 daniel 502: rpm->extra->max_resources);
503: if (rpm->extra->resources == NULL) {
1.48 veillard 504: fprintf(stderr, ": ran out of memory\n");
505: exit(1);
506: }
1.58 daniel 507: rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
1.1 veillard 508: } else {
1.58 daniel 509: rpm->extra->max_resources = count + 1;
1.61 daniel 510: rpm->extra->resources = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) *
1.58 daniel 511: rpm->extra->max_resources);
512: if (rpm->extra->resources == NULL) {
1.48 veillard 513: fprintf(stderr, ": ran out of memory\n");
514: exit(1);
1.1 veillard 515: }
1.58 daniel 516: rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
517: rpm->extra->nb_resources = 1;
1.1 veillard 518:
1.58 daniel 519: for (i = 0, j = rpm->extra->nb_resources; i < count;i++) {
1.53 veillard 520: if (!checkResourceName(((char **) p)[i])) continue;
1.58 daniel 521: rpm->extra->resources[j++] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4 veillard 522: }
1.58 daniel 523: rpm->extra->nb_resources = j;
1.4 veillard 524: }
1.62 daniel 525: ENTRY_CLEANUP(p);
1.4 veillard 526:
527: val = getTagNumber("RPMTAG_REQUIRENAME");
528: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.58 daniel 529: rpm->extra->nb_requires = 0;
530: rpm->extra->requires = NULL;
1.4 veillard 531: } else {
1.58 daniel 532: rpm->extra->max_requires = count;
1.61 daniel 533: rpm->extra->requires = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) *
1.58 daniel 534: rpm->extra->max_requires);
535: if (rpm->extra->requires == NULL) {
1.48 veillard 536: fprintf(stderr, ": ran out of memory\n");
537: exit(1);
1.4 veillard 538: }
539:
1.58 daniel 540: rpm->extra->nb_requires = 0;
1.53 veillard 541: for (i = 0, j = 0; i < count;i++) {
542: if (!checkResourceName(((char **) p)[i])) continue;
1.58 daniel 543: rpm->extra->requires[j++] = rpmRequAdd(((char **) p)[i], rpm, installed);
1.1 veillard 544: }
1.58 daniel 545: rpm->extra->nb_requires = j;
1.5 veillard 546: }
1.62 daniel 547: ENTRY_CLEANUP(p);
1.5 veillard 548: val = getTagNumber("RPMTAG_FILENAMES");
549: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.58 daniel 550: rpm->extra->filelist = NULL; /* No filelist in the package ! */
1.5 veillard 551: } else {
552: char *ptr = buffer;
1.42 veillard 553:
1.5 veillard 554: for (i = 0; i < count;i++) {
1.42 veillard 555: if ((ptr - buffer) > (buffer_size - 1024)) {
556: int delta = ptr - buffer;
557:
1.41 veillard 558: buffer_size *= 2;
1.61 daniel 559: buffer = (char *) debugRealloc(buffer, buffer_size);
1.42 veillard 560: if (buffer == NULL) {
561: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
562: buffer_size, strerror(errno));
563: exit(1);
564: }
565: ptr = &buffer[delta];
1.41 veillard 566: }
1.5 veillard 567: ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
568: }
1.61 daniel 569: rpm->extra->filelist = debugStrdup(buffer);
1.1 veillard 570: }
1.62 daniel 571: ENTRY_CLEANUP(p);
1.1 veillard 572:
1.37 veillard 573: /* Add the package files to the real filesystem tree if asked for */
1.58 daniel 574: if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
1.37 veillard 575: char *cur, *filename;
576:
1.58 daniel 577: cur = rpm->extra->filelist;
1.37 veillard 578: while ((*cur != '\0') && (*cur != '/')) cur++;
579: filename = cur;
580: while (*cur != '\0') {
581: if ((*cur == '\n') || (*cur == '\r')) {
582: if (cur != filename)
583: rpmAddRealFile(dir->root, filename, rpm);
584: while ((*cur != '\0') && (*cur != '/')) cur++;
585: filename = cur;
586: } else
587: cur++;
588: }
589: if (cur != filename)
590: rpmAddRealFile(dir->root, filename, rpm);
591: }
1.17 veillard 592:
593: /* Register this package */
594: rpmAddSoftware(rpm);
1.7 veillard 595:
596: /* dump the HTML related to this package */
1.56 daniel 597: if ((rpm2html_dump_html) && (dir->html))
1.40 httpng 598: dumpRpmHtml(rpm, tree);
599: if (rpm2html_dump_rdf)
600: dumpRpmRdf(rpm, tree);
1.7 veillard 601:
1.58 daniel 602: /* free the extra data */
603: rpmFreeExtraData(rpm);
1.8 veillard 604:
605: /* increment the counters */
1.11 veillard 606: if (installed) {
607: rpm2html_install_files++;
1.21 veillard 608: rpm2html_install_size += rpm->size / 1024;
1.11 veillard 609: } else {
610: rpm2html_files++;
1.21 veillard 611: rpm2html_size += rpm->size / 1024;
1.11 veillard 612: }
1.7 veillard 613:
1.32 veillard 614: return(rpm);
1.11 veillard 615: }
616:
617: /*
618: * rpmOpen : open an RPM file, read and parse the header and
619: * fill the informations in the database.
620: */
1.35 veillard 621: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32 veillard 622: rpmDataPtr cur;
1.64 daniel 623: #if defined(HAVE_RPM_RPMIO_H)
624: FD_t fd;
625: #else
1.11 veillard 626: int fd;
1.64 daniel 627: #define fdOpen(_a, _b, _c) open((_a), (_b))
628: #define fdClose(_a) close(_a)
629: #endif
1.11 veillard 630: int rc;
631: Header h = NULL;
632: int isSource;
633: char buffer[500];
1.20 veillard 634: struct stat buf;
1.11 veillard 635:
636: /* open the file for reading */
1.35 veillard 637: if (tree->htmlpath[0] != '\0')
638: sprintf(buffer, "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24 veillard 639: else
640: sprintf(buffer, "%s/%s", dir->rpmdir, nameRpm);
1.64 daniel 641: if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
1.11 veillard 642: fprintf(stderr, "open of %s failed: %s\n", buffer,
643: strerror(errno));
1.32 veillard 644: return(NULL);
1.11 veillard 645: }
646:
1.20 veillard 647: stat(buffer, &buf);
648:
1.11 veillard 649: /* read the RPM header */
650: rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
651: switch (rc) {
652: case 0:
653: if (!h) {
654: fprintf(stderr,
655: "old format source packages cannot be queried\n");
1.32 veillard 656: return(NULL);
1.11 veillard 657: }
658: break;
659: case 1:
660: fprintf(stderr, "%s does not appear to be a RPM package\n",
661: nameRpm);
1.32 veillard 662: return(NULL);
1.11 veillard 663: case 2:
664: fprintf(stderr, "query of %s failed\n", nameRpm);
1.32 veillard 665: return(NULL);
1.11 veillard 666: default:
667: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
668: nameRpm, rc);
1.32 veillard 669: return(NULL);
1.11 veillard 670: }
671:
1.52 daniel 672: cur = rpmAnalyze(nameRpm, h, dir, tree, buf.st_mtime, isSource);
1.11 veillard 673:
674: /* free the header and close the descriptor */
675: headerFree(h);
1.64 daniel 676: fdClose(fd);
1.1 veillard 677:
1.32 veillard 678: return(cur);
1.6 veillard 679: }
680:
681: /*
1.22 veillard 682: * Scan one directory for RPM files this is where the recursive handling
683: * is done.
1.6 veillard 684: */
1.35 veillard 685: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
686: rpmSubdirPtr subtree;
1.32 veillard 687: rpmDataPtr ret = NULL, cur;
1.7 veillard 688: char *filename;
1.22 veillard 689: static char path[2000];
1.23 veillard 690: struct stat buf;
1.7 veillard 691: int len;
1.39 veillard 692: DIR *d;
693: struct dirent *file;
1.6 veillard 694:
1.24 veillard 695:
696: /*
697: * Create the directory for the HTML pages
698: */
1.56 daniel 699: if ((rpm2html_dump_html) && (dir->html)) {
1.45 veillard 700: if (tree->htmlpath[0] != '\0')
701: sprintf(path, "%s/%s", dir->dir, tree->htmlpath);
702: else
703: sprintf(path, "%s", dir->dir);
704: createDirectory(path);
705: }
1.43 veillard 706:
707: /*
708: * Create the directory for the RDF pages
709: if (rpm2html_rdf_dir != NULL) {
710: if (tree->htmlpath[0] != '\0')
711: sprintf(path, "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
712: else
713: sprintf(path, "%s", rpm2html_rdf_dir);
714: createDirectory(path);
715: }
1.47 veillard 716: */
1.24 veillard 717:
718: /*
719: * Scan the repository.
720: */
1.35 veillard 721: if (tree->rpmpath[0] != '\0')
722: sprintf(path, "%s/%s", dir->rpmdir, tree->rpmpath);
1.24 veillard 723: else
724: sprintf(path, "%s", dir->rpmdir);
1.51 veillard 725: if (rpm2htmlVerbose > 1)
1.24 veillard 726: fprintf(stderr, "Scanning directory %s\n", path);
727:
1.39 veillard 728: d = opendir(path);
729: if (d == NULL) {
1.24 veillard 730: fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6 veillard 731: strerror(errno));
1.35 veillard 732: rpmRemoveSubdir(tree);
1.36 veillard 733: rpmFreeSubdir(tree);
1.32 veillard 734: return(NULL);
1.6 veillard 735: } else {
1.39 veillard 736: while ((file = readdir(d)) != NULL) {
1.32 veillard 737: cur = NULL;
1.39 veillard 738: filename = file->d_name;
1.7 veillard 739: len = strlen(filename);
1.24 veillard 740:
741: /*
742: * Compute the full path
743: */
1.35 veillard 744: if (tree->rpmpath[0] != '\0')
745: sprintf(path, "%s/%s/%s", dir->rpmdir, tree->rpmpath,
746: filename);
1.22 veillard 747: else
1.24 veillard 748: sprintf(path, "%s/%s", dir->rpmdir, filename);
1.22 veillard 749:
750: /*
1.25 veillard 751: * Stat() the file to detect directory and symlimks
752: */
1.30 veillard 753: if (lstat(path, &buf) != 0) {
1.25 veillard 754: fprintf(stderr, "Couldn't stat(%s)\n", path);
755: continue;
756: }
1.35 veillard 757:
1.25 veillard 758: /*
1.23 veillard 759: * Check for RPM files by looking at the suffix
1.54 veillard 760: * Note that SuSE source RPMs have a ".spm" suffix
1.63 daniel 761: * We may or may not follow symlinks to RPM files
1.22 veillard 762: */
1.63 daniel 763: if (((len >= 5) &&
1.54 veillard 764: (!strcasecmp(&filename[len - 4], ".rpm"))) ||
765: ((len >= 5) &&
766: (!strcasecmp(&filename[len - 4], ".spm")))) {
1.63 daniel 767:
1.65 ! daniel 768: if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) {
1.63 daniel 769: if (rpm2htmlVerbose)
770: fprintf(stderr, "Dropping symlink %s\n", path);
771: continue;
772: }
1.35 veillard 773: cur = rpmOpen(filename, dir, tree);
1.63 daniel 774: }
775:
776: /*
777: * Don't follow of analyze symlinks,
778: */
1.65 ! daniel 779: else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0)) {
1.63 daniel 780: if (rpm2htmlVerbose)
781: fprintf(stderr, "Dropping symlink %s\n", path);
782: continue;
1.44 veillard 783: }
784:
785: /*
786: * Check for RDF files by looking at the suffix
787: */
788: else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
789: cur = rpmOpenRdf(filename, dir, tree);
1.22 veillard 790: }
1.35 veillard 791:
1.22 veillard 792: /*
1.23 veillard 793: * Else if this is a directory, recurse !
1.22 veillard 794: */
1.25 veillard 795: else if (S_ISDIR(buf.st_mode)) {
796: if (filename[0] != '.') {
1.57 daniel 797: subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
1.35 veillard 798: cur = rpmOneDirScan(dir, subtree);
1.25 veillard 799: }
1.22 veillard 800: }
1.32 veillard 801: if (cur != NULL) ret = rpmAddList(ret, cur);
1.7 veillard 802: }
1.6 veillard 803: }
1.39 veillard 804: closedir(d);
1.33 veillard 805:
806: /*
807: * Dump the pages related to this directory.
808: */
1.35 veillard 809: if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36 veillard 810: else {
811: rpmRemoveSubdir(tree);
812: rpmFreeSubdir(tree);
813: }
1.35 veillard 814:
1.32 veillard 815: return(ret);
1.22 veillard 816: }
817:
818: /*
819: * Scan a directory for RPM files.
820: */
1.35 veillard 821: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37 veillard 822: rpmSubdirPtr cur;
823: rpmDataPtr ret;
824:
1.56 daniel 825: if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
1.37 veillard 826: dir->root = rpmCreateRealRoot();
827: }
828: cur = rpmNewSubdir(tree, dir->name,
1.57 daniel 829: dir->subdir == NULL ? "" : dir->subdir, "", dir->color,
830: dir->html);
1.37 veillard 831: ret = rpmOneDirScan(dir, cur);
1.38 veillard 832: rpmDumpHtmlRealRoot(dir);
1.37 veillard 833: return(ret);
1.6 veillard 834: }
835:
836: /*
1.11 veillard 837: * Scan the local RPM database for RPM files.
838: */
1.32 veillard 839: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37 veillard 840: static char path[2000];
1.32 veillard 841: rpmDataPtr ret = NULL, cur;
1.11 veillard 842: rpmdb db;
843: Header h = NULL;
1.32 veillard 844: int offset;
1.11 veillard 845: char *prefix = "/";
846:
1.37 veillard 847: /*
848: * Create the directory for the HTML pages
849: */
1.56 daniel 850: if ((rpm2html_dump_html) && (dir->html)) {
1.45 veillard 851: if (dir->subdir)
852: sprintf(path, "%s/%s", dir->dir, dir->subdir);
853: else
854: sprintf(path, "%s", dir->dir);
855: createDirectory(path);
856: }
857:
858: /*
859: * Create the directory for the RDF pages
860: */
861: if (rpm2html_rdf_dir != NULL) {
862: if (dir->subdir)
863: sprintf(path, "%s/%s", rpm2html_rdf_dir, dir->subdir);
864: else
865: sprintf(path, "%s", rpm2html_rdf_dir);
866: createDirectory(path);
867: }
1.37 veillard 868:
1.11 veillard 869: if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32 veillard 870: return(NULL);
1.11 veillard 871: }
872: offset = rpmdbFirstRecNum(db);
873: while (offset) {
874: h = rpmdbGetRecord(db, offset);
875: if (!h) {
876: fprintf(stderr, "could not read database record!\n");
1.32 veillard 877: return(ret);
1.11 veillard 878: }
1.52 daniel 879: cur = rpmAnalyze(NULL, h, dir, NULL, 0, 0);
1.32 veillard 880: if (cur != NULL) ret = rpmAddList(ret, cur);
1.11 veillard 881: headerFree(h);
882: offset = rpmdbNextRecNum(db, offset);
883: }
884: rpmdbClose(db);
885:
1.32 veillard 886: return(ret);
1.11 veillard 887: }
888:
889: /*
1.6 veillard 890: * Scan all registered directories.
891: * One fist check for completeness of the informations in
892: * the rpmDir structure.
893: */
894:
1.32 veillard 895: rpmDataPtr rpmDirScanAll(void) {
1.18 veillard 896: rpmDirPtr dir, next;
1.32 veillard 897: rpmDataPtr ret = NULL, cur;
1.46 veillard 898: int maxLists = 50;
899: rpmDataPtr *rpmLists;
1.35 veillard 900: int nbLists = 0;
901: int i;
1.18 veillard 902:
903: /*
904: * first reverse the list ....
905: */
906: dir = dirList;
907: dirList = NULL;
908: while (dir != NULL) {
909: next = dir->next;
910: dir->next = dirList;
911: dirList = dir;
912: dir = next;
913: }
1.57 daniel 914: dir = dirList;
1.18 veillard 915:
1.35 veillard 916: /*
917: * Allocate a directory tree.
918: */
1.57 daniel 919: dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1.6 veillard 920:
1.61 daniel 921: rpmLists = (rpmDataPtr *) debugMalloc(maxLists * sizeof(rpmDataPtr));
1.46 veillard 922: if (rpmLists == NULL) {
923: fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
924: exit(1);
925: }
926:
1.6 veillard 927: while (dir != NULL) {
1.32 veillard 928: cur = NULL;
929:
1.14 veillard 930: /*
931: * Override default setting.
932: */
1.15 veillard 933: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.61 daniel 934: dir->maint = debugStrdup(rpm2html_maint);
1.15 veillard 935: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.61 daniel 936: dir->mail = debugStrdup(rpm2html_mail);
1.15 veillard 937: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.61 daniel 938: dir->ftp = debugStrdup(rpm2html_ftp);
1.15 veillard 939: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.61 daniel 940: dir->ftpsrc = debugStrdup(rpm2html_ftpsrc);
1.15 veillard 941: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.61 daniel 942: dir->dir = debugStrdup(rpm2html_dir);
1.15 veillard 943: if ((dir->host == NULL) && (rpm2html_host != NULL))
1.61 daniel 944: dir->host = debugStrdup(rpm2html_host);
1.15 veillard 945: if ((dir->name == NULL) && (rpm2html_name != NULL))
1.61 daniel 946: dir->name = debugStrdup(rpm2html_name);
1.15 veillard 947: if ((dir->url == NULL) && (rpm2html_url != NULL))
1.61 daniel 948: dir->url = debugStrdup(rpm2html_url);
1.14 veillard 949:
950: if (dir->rpmdir == NULL) {
1.6 veillard 951: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.14 veillard 952: } else if (!strcmp(dir->rpmdir, "localbase")) {
1.11 veillard 953: /* Scan the local RPM database instead of a directory */
1.32 veillard 954: cur = rpmBaseScan(dir);
1.7 veillard 955: } else if (dir->ftp == NULL) {
956: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14 veillard 957: dir->rpmdir);
1.6 veillard 958: } else {
1.51 veillard 959: if (rpm2htmlVerbose)
1.16 veillard 960: fprintf(stderr, "Scanning directory %s for RPMs\n",dir->rpmdir);
1.35 veillard 961: cur = rpmDirScan(dir, dirTree);
1.6 veillard 962: }
963:
1.35 veillard 964: if (cur != NULL) {
1.46 veillard 965: if (nbLists >= maxLists) {
966: maxLists *= 2;
1.61 daniel 967: rpmLists = (rpmDataPtr *) debugRealloc(rpmLists,
1.46 veillard 968: maxLists * sizeof(rpmDataPtr));
969: if (rpmLists == NULL) {
970: fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
971: exit(1);
1.35 veillard 972: }
973: }
1.46 veillard 974: rpmLists[nbLists] = cur;
975: nbLists++;
1.39 veillard 976: }
977: if (dir->root != NULL) {
1.48 veillard 978: /************************************************
1.39 veillard 979: if (rpm2html_build_tree)
980: treeRoot = rpmMergeRealRoots(treeRoot, dir->root);
981: else
1.48 veillard 982: ************************************************/
983: rpmDestroyRealRoot(dir->root);
984: dir->root = NULL;
1.35 veillard 985: }
1.32 veillard 986:
1.6 veillard 987: dir = dir->next;
988: }
1.35 veillard 989: for (i = 0;i < nbLists;i++)
990: ret = rpmAddList(ret, rpmLists[i]);
1.61 daniel 991: debugFree(rpmLists);
1.32 veillard 992: return(ret);
1.60 daniel 993: }
994:
995: /*
996: * Cleanup the global variables from this module
997: */
998: void rpmopenCleanup(void) {
999: if (buffer != NULL)
1.61 daniel 1000: debugFree(buffer);
1.60 daniel 1001: buffer = NULL;
1002: buffer_size = 50 * 1024 * sizeof(char);
1.1 veillard 1003: }
1004:
Webmaster