Annotation of rpm2html/rpmopen.c, revision 1.46
1.1 veillard 1: /*
2: * rpmopen.c : open an extract informations from RPM files.
3: *
1.11 veillard 4: * Copyright (c) 1997 Daniel Veillard <veillard@apocalypse.org>
1.9 veillard 5: * See COPYING for the status of this software.
1.1 veillard 6: *
1.46 ! veillard 7: * $Id: rpmopen.c,v 1.45 1998/05/10 07:45:22 veillard Exp $
1.1 veillard 8: */
9:
1.9 veillard 10: #include <config.h>
1.1 veillard 11: #include <sys/types.h>
12: #include <sys/stat.h>
1.9 veillard 13: #ifdef HAVE_FCNTL_H
1.1 veillard 14: #include <fcntl.h>
1.9 veillard 15: #endif
1.1 veillard 16: #include <stdio.h>
17: #include <stdlib.h>
18: #include <string.h>
1.9 veillard 19: #ifdef HAVE_UNISTD_H
1.1 veillard 20: #include <unistd.h>
1.9 veillard 21: #endif
1.6 veillard 22: #include <dirent.h>
1.13 veillard 23: #include <errno.h>
1.31 veillard 24: #include <time.h>
1.1 veillard 25:
26: #include <rpm/rpmlib.h>
27:
28: #include "rpmdata.h"
1.7 veillard 29: #include "html.h"
1.40 httpng 30: #include "rdf.h"
1.8 veillard 31: #include "rpm2html.h"
1.12 veillard 32: #include "language.h"
1.1 veillard 33:
34: /*
35: * Get the internal number associated to an RPM tag.
36: */
37: static int getTagNumber(char *tag) {
38: int i;
39: const struct headerTagTableEntry * t;
40:
41: for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
42: if (!strcasecmp(tag, t->name)) return(t->val);
43: }
44: fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
45: return(-1);
46: }
47:
48: /*
1.11 veillard 49: * rpmAnalyze : analyze an RPM record, read and parse the header and
50: * fill the informations in the database.
1.1 veillard 51: */
1.36 veillard 52: rpmDataPtr rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir,
53: rpmSubdirPtr tree, time_t stamp) {
1.11 veillard 54: int installed = dir->installbase;
1.2 veillard 55: char * name = NULL, * version = NULL, * release = NULL;
1.1 veillard 56: int_32 count, type;
1.2 veillard 57: void * p = NULL;
1.10 veillard 58: int val, i, j;
1.1 veillard 59: rpmDataPtr rpm = NULL;
1.41 veillard 60: static char *buffer = NULL;
61: static int buffer_size = 50 * 1024 * sizeof(char);
1.11 veillard 62: static char nameBuffer[500];
1.1 veillard 63:
1.41 veillard 64: if (buffer == NULL) {
65: buffer = (char *) malloc(buffer_size);
66: if (buffer == NULL) {
67: fprintf(stderr, "cannot allocate %d bytes: %s\n", buffer_size,
68: strerror(errno));
69: exit(1);
70: }
71: }
72:
1.1 veillard 73: /* extract informations from the header */
74: headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
75: headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
76: headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
77:
78: /* allocate a new rpmData block, fill it */
79: rpm = (rpmDataPtr) malloc(sizeof(rpmData));
80: if (rpm == NULL) {
1.41 veillard 81: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
82: strerror(errno));
83: return(NULL);
1.1 veillard 84: }
1.44 veillard 85: memset(rpm, 0, sizeof(rpmData));
1.6 veillard 86: rpm->dir = dir;
1.36 veillard 87: if (tree) {
88: if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
89: rpm->subdir = strdup(tree->rpmpath);
90: else
91: rpm->subdir = NULL;
92: } else
93: rpm->subdir = NULL;
1.20 veillard 94: rpm->stamp = stamp;
1.1 veillard 95: rpm->name = strdup(name);
96: rpm->version = strdup(version);
97: rpm->release = strdup(release);
98:
1.26 veillard 99: /* get all the resources provided by this RPM */
1.2 veillard 100: if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.27 veillard 101: rpm->summary = strdup(localizedStrings[LANG_NO_SUMMARY]);
1.2 veillard 102: } else {
1.40 httpng 103: rpm->summary = strdup((char *) p);
1.2 veillard 104: }
1.28 veillard 105: if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p ||
106: (type != RPM_STRING_TYPE)) {
1.27 veillard 107: rpm->description = strdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.2 veillard 108: } else {
1.40 httpng 109: rpm->description = strdup((char *) p);
1.2 veillard 110: }
1.28 veillard 111: if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p ||
112: (type != RPM_STRING_TYPE)) {
1.27 veillard 113: rpm->distribution = strdup(localizedStrings[LANG_UNKNOWN]);
1.2 veillard 114: } else {
115: rpm->distribution = strdup((char *) p);
116: }
1.28 veillard 117: if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p ||
118: (type != RPM_STRING_TYPE)) {
1.29 veillard 119: if (type == RPM_INT8_TYPE) {
120: /*
1.32 veillard 121: * Old packages.
1.29 veillard 122: */
123: switch (*((char *) p)) {
124: case 1:
125: rpm->arch = strdup("i386");
126: break;
127: default:
128: rpm->arch = strdup("i386");
129: break;
130: }
131: } else
132: rpm->arch = strdup(localizedStrings[LANG_NONE]);
1.11 veillard 133: if (nameRpm == NULL) {
1.12 veillard 134: sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
1.11 veillard 135: nameRpm = nameBuffer;
136: }
1.2 veillard 137: } else {
138: rpm->arch = strdup((char *) p);
1.11 veillard 139: if (nameRpm == NULL) {
1.12 veillard 140: sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
141: name, version, release, (char *)p);
1.11 veillard 142: nameRpm = nameBuffer;
143: }
1.2 veillard 144: }
1.28 veillard 145: if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p ||
146: (type != RPM_STRING_TYPE)) {
1.29 veillard 147: if (type == RPM_INT8_TYPE) {
148: /*
1.32 veillard 149: * Old packages.
1.29 veillard 150: */
151: switch (*((char *) p)) {
152: case 1:
153: rpm->os = strdup("linux");
154: break;
155: default:
156: rpm->os = strdup("linux");
157: break;
158: }
159: } else
160: rpm->os = strdup("");
1.7 veillard 161: } else {
162: rpm->os = strdup((char *) p);
163: }
1.28 veillard 164: if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p ||
165: (type != RPM_STRING_TYPE)) {
1.7 veillard 166: rpm->vendor = NULL;
1.2 veillard 167: } else {
168: rpm->vendor = strdup((char *) p);
169: }
1.28 veillard 170: if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p ||
171: (type != RPM_STRING_TYPE)) {
1.27 veillard 172: rpm->group = strdup(localizedStrings[LANG_NO_GROUP]);
1.2 veillard 173: } else {
174: rpm->group = strdup((char *) p);
175: }
1.28 veillard 176: if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p ||
177: (type != RPM_STRING_TYPE)) {
1.27 veillard 178: rpm->host = strdup(localizedStrings[LANG_NO_HOST]);
1.2 veillard 179: } else {
180: rpm->host = strdup((char *) p);
181: }
182: if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
183: rpm->size = 0;
184: } else {
185: rpm->size = *((int *) p);
186: }
1.11 veillard 187: if (installed) {
188: if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
189: rpm->date = 0;
190: } else {
191: rpm->date = *((int_32 *) p);
192: }
1.2 veillard 193: } else {
1.11 veillard 194: if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
195: rpm->date = 0;
196: } else {
197: rpm->date = *((int_32 *) p);
198: }
1.2 veillard 199: }
1.28 veillard 200: if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p ||
201: (type != RPM_STRING_TYPE)) {
1.27 veillard 202: rpm->srcrpm = strdup("");
1.2 veillard 203: } else {
204: rpm->srcrpm = strdup((char *) p);
205: }
1.28 veillard 206: if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p ||
207: (type != RPM_STRING_TYPE)) {
1.7 veillard 208: rpm->url = NULL;
209: } else {
210: rpm->url = strdup((char *) p);
211: }
1.28 veillard 212: if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p ||
213: (type != RPM_STRING_TYPE)) {
1.7 veillard 214: rpm->packager = NULL;
215: } else {
216: rpm->packager = strdup((char *) p);
217: }
1.28 veillard 218: if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p ||
219: (type != RPM_STRING_TYPE)) {
1.7 veillard 220: rpm->copyright = NULL;
221: } else {
222: rpm->copyright = strdup((char *) p);
223: }
1.31 veillard 224: /* Pick up changelog entries */
225: if (!headerGetEntry(h, RPMTAG_CHANGELOGTEXT, &type, &p, &count) || !p) {
226: rpm->changelog = NULL;
227: } else {
228: time_t *dates;
229: char **names;
230: char **holdp = (char **)p;
231: char *cp;
232: struct tm *tm_buf;
233: int i, len, pos;
234: char date_string[50];
235: char *res = buffer;
1.42 veillard 236:
1.31 veillard 237: *res = '\0';
238: headerGetEntry(h, RPMTAG_CHANGELOGTIME, &type, (void *)&dates, &count);
239: headerGetEntry(h, RPMTAG_CHANGELOGNAME, &type, (void *)&names, &count);
240: for (i = 0; i < count; i++) {
1.42 veillard 241: if ((res - buffer) > (buffer_size - 1024)) {
242: int delta = res - buffer;
243:
1.41 veillard 244: buffer_size *= 2;
245: buffer = (char *) realloc(buffer, buffer_size);
1.42 veillard 246: if (buffer == NULL) {
247: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
248: buffer_size, strerror(errno));
249: exit(1);
250: }
251: res = &buffer[delta];
1.41 veillard 252: }
1.31 veillard 253: tm_buf = localtime(&dates[i]);
254: strftime(date_string, sizeof(date_string) - 1, "%a %b %d %Y", tm_buf);
255: len = sprintf(res, "* %s %s\n", date_string, names[i]);
256: res += len;
257: cp = holdp[i];
258: pos = 0;
259: while (*cp) {
260: if (pos++ == 0) {
261: *res++ = ' ';
262: *res++ = ' ';
263: }
264: *res++ = *cp;
265: if (*cp++ == '\n') pos = 0;
266: }
267: *res++ = '\n';
268: }
269: *res = '\0';
270: rpm->changelog = strdup(buffer);
271: }
1.7 veillard 272: if (rpm->vendor == NULL) {
1.15 veillard 273: if (rpm->packager != NULL) rpm->vendor = strdup(rpm->packager);
274: else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
1.7 veillard 275: }
1.2 veillard 276:
1.11 veillard 277: rpm->filename = strdup(nameRpm);
278:
1.26 veillard 279: /* package-xxx.rpm provides the resource "package" */
280: rpm->nb_resources = 1;
281: rpm->resources[0] = rpmRessAdd(name, rpm, installed);
1.10 veillard 282:
1.1 veillard 283: val = getTagNumber("RPMTAG_PROVIDES");
284: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.26 veillard 285: rpm->nb_resources = 1;
1.1 veillard 286: } else {
1.26 veillard 287: if (count >= MAX_RES) {
288: fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n",
289: MAX_RES);
290: count = MAX_RES;
1.1 veillard 291: }
292:
1.26 veillard 293: for (i = 0, j = rpm->nb_resources; i < count;j++, i++) {
294: rpm->resources[j] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4 veillard 295: }
1.26 veillard 296: rpm->nb_resources += count;
1.4 veillard 297: }
298:
299: val = getTagNumber("RPMTAG_REQUIRENAME");
300: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
301: rpm->nb_requires = 0;
302: } else {
303: if (count >= MAX_REQU) {
304: fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n",
305: MAX_REQU);
306: count = MAX_REQU;
307: }
308:
309: rpm->nb_requires = count;
310: for (i = 0; i < count;i++) {
1.11 veillard 311: rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed);
1.1 veillard 312: }
1.5 veillard 313: }
314: val = getTagNumber("RPMTAG_FILENAMES");
315: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.7 veillard 316: rpm->filelist = NULL; /* No filelist in the package ! */
1.5 veillard 317: } else {
318: char *ptr = buffer;
1.42 veillard 319:
1.5 veillard 320: for (i = 0; i < count;i++) {
1.42 veillard 321: if ((ptr - buffer) > (buffer_size - 1024)) {
322: int delta = ptr - buffer;
323:
1.41 veillard 324: buffer_size *= 2;
325: buffer = (char *) realloc(buffer, buffer_size);
1.42 veillard 326: if (buffer == NULL) {
327: fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
328: buffer_size, strerror(errno));
329: exit(1);
330: }
331: ptr = &buffer[delta];
1.41 veillard 332: }
1.5 veillard 333: ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
334: }
335: rpm->filelist = strdup(buffer);
1.1 veillard 336: }
337:
1.37 veillard 338: /* Add the package files to the real filesystem tree if asked for */
339: if ((dir->build_tree != 0) && (rpm->filelist != NULL)) {
340: char *cur, *filename;
341:
342: cur = rpm->filelist;
343: while ((*cur != '\0') && (*cur != '/')) cur++;
344: filename = cur;
345: while (*cur != '\0') {
346: if ((*cur == '\n') || (*cur == '\r')) {
347: if (cur != filename)
348: rpmAddRealFile(dir->root, filename, rpm);
349: while ((*cur != '\0') && (*cur != '/')) cur++;
350: filename = cur;
351: } else
352: cur++;
353: }
354: if (cur != filename)
355: rpmAddRealFile(dir->root, filename, rpm);
356: }
1.17 veillard 357:
358: /* Register this package */
359: rpmAddSoftware(rpm);
1.7 veillard 360:
361: /* dump the HTML related to this package */
1.40 httpng 362: if (rpm2html_dump_html)
363: dumpRpmHtml(rpm, tree);
364: if (rpm2html_dump_rdf)
365: dumpRpmRdf(rpm, tree);
1.7 veillard 366:
367: /* free large amount of data not used later */
368: if (rpm->filelist) free(rpm->filelist);
1.15 veillard 369: rpm->filelist = NULL;
1.7 veillard 370: if (rpm->copyright) free(rpm->copyright);
1.15 veillard 371: rpm->copyright = NULL;
1.31 veillard 372: if (rpm->changelog) free(rpm->changelog);
373: rpm->changelog = NULL;
1.15 veillard 374: if (rpm->description) free(rpm->description);
375: rpm->description = NULL;
1.8 veillard 376:
377: /* increment the counters */
1.11 veillard 378: if (installed) {
379: rpm2html_install_files++;
1.21 veillard 380: rpm2html_install_size += rpm->size / 1024;
1.11 veillard 381: } else {
382: rpm2html_files++;
1.21 veillard 383: rpm2html_size += rpm->size / 1024;
1.11 veillard 384: }
1.7 veillard 385:
1.32 veillard 386: return(rpm);
1.11 veillard 387: }
388:
389: /*
390: * rpmOpen : open an RPM file, read and parse the header and
391: * fill the informations in the database.
392: */
1.35 veillard 393: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32 veillard 394: rpmDataPtr cur;
1.11 veillard 395: int fd;
396: int rc;
397: Header h = NULL;
398: int isSource;
399: char buffer[500];
1.20 veillard 400: struct stat buf;
1.11 veillard 401:
402: /* open the file for reading */
1.35 veillard 403: if (tree->htmlpath[0] != '\0')
404: sprintf(buffer, "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24 veillard 405: else
406: sprintf(buffer, "%s/%s", dir->rpmdir, nameRpm);
1.11 veillard 407: if ((fd = open(buffer, O_RDONLY)) < 0) {
408: fprintf(stderr, "open of %s failed: %s\n", buffer,
409: strerror(errno));
1.32 veillard 410: return(NULL);
1.11 veillard 411: }
412:
1.20 veillard 413: stat(buffer, &buf);
414:
1.11 veillard 415: /* read the RPM header */
416: rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
417: switch (rc) {
418: case 0:
419: if (!h) {
420: fprintf(stderr,
421: "old format source packages cannot be queried\n");
1.32 veillard 422: return(NULL);
1.11 veillard 423: }
424: break;
425: case 1:
426: fprintf(stderr, "%s does not appear to be a RPM package\n",
427: nameRpm);
1.32 veillard 428: return(NULL);
1.11 veillard 429: case 2:
430: fprintf(stderr, "query of %s failed\n", nameRpm);
1.32 veillard 431: return(NULL);
1.11 veillard 432: default:
433: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
434: nameRpm, rc);
1.32 veillard 435: return(NULL);
1.11 veillard 436: }
437:
1.36 veillard 438: cur = rpmAnalyze(nameRpm, h, dir, tree, buf.st_mtime);
1.11 veillard 439:
440: /* free the header and close the descriptor */
441: headerFree(h);
442: close(fd);
1.1 veillard 443:
1.32 veillard 444: return(cur);
1.6 veillard 445: }
446:
447: /*
1.22 veillard 448: * Scan one directory for RPM files this is where the recursive handling
449: * is done.
1.6 veillard 450: */
1.35 veillard 451: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
452: rpmSubdirPtr subtree;
1.32 veillard 453: rpmDataPtr ret = NULL, cur;
1.7 veillard 454: char *filename;
1.22 veillard 455: static char path[2000];
1.23 veillard 456: struct stat buf;
1.7 veillard 457: int len;
1.39 veillard 458: DIR *d;
459: struct dirent *file;
1.6 veillard 460:
1.24 veillard 461:
462: /*
463: * Create the directory for the HTML pages
464: */
1.45 veillard 465: if (rpm2html_dump_html) {
466: if (tree->htmlpath[0] != '\0')
467: sprintf(path, "%s/%s", dir->dir, tree->htmlpath);
468: else
469: sprintf(path, "%s", dir->dir);
470: createDirectory(path);
471: }
1.43 veillard 472:
473: /*
474: * Create the directory for the RDF pages
475: */
476: if (rpm2html_rdf_dir != NULL) {
477: if (tree->htmlpath[0] != '\0')
478: sprintf(path, "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
479: else
480: sprintf(path, "%s", rpm2html_rdf_dir);
481: createDirectory(path);
482: }
1.24 veillard 483:
484: /*
485: * Scan the repository.
486: */
1.35 veillard 487: if (tree->rpmpath[0] != '\0')
488: sprintf(path, "%s/%s", dir->rpmdir, tree->rpmpath);
1.24 veillard 489: else
490: sprintf(path, "%s", dir->rpmdir);
1.35 veillard 491: if (verbose > 1)
1.24 veillard 492: fprintf(stderr, "Scanning directory %s\n", path);
493:
1.39 veillard 494: d = opendir(path);
495: if (d == NULL) {
1.24 veillard 496: fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6 veillard 497: strerror(errno));
1.35 veillard 498: rpmRemoveSubdir(tree);
1.36 veillard 499: rpmFreeSubdir(tree);
1.32 veillard 500: return(NULL);
1.6 veillard 501: } else {
1.39 veillard 502: while ((file = readdir(d)) != NULL) {
1.32 veillard 503: cur = NULL;
1.39 veillard 504: filename = file->d_name;
1.7 veillard 505: len = strlen(filename);
1.24 veillard 506:
507: /*
508: * Compute the full path
509: */
1.35 veillard 510: if (tree->rpmpath[0] != '\0')
511: sprintf(path, "%s/%s/%s", dir->rpmdir, tree->rpmpath,
512: filename);
1.22 veillard 513: else
1.24 veillard 514: sprintf(path, "%s/%s", dir->rpmdir, filename);
1.22 veillard 515:
516: /*
1.25 veillard 517: * Stat() the file to detect directory and symlimks
518: */
1.30 veillard 519: if (lstat(path, &buf) != 0) {
1.25 veillard 520: fprintf(stderr, "Couldn't stat(%s)\n", path);
521: continue;
522: }
1.35 veillard 523:
1.25 veillard 524: /*
525: * Don't follow of analyze symlinks,
526: */
527: if (S_ISLNK(buf.st_mode)) {
528: if (verbose)
529: fprintf(stderr, "Dropping symlink %s\n", path);
530: continue;
531: }
1.35 veillard 532:
1.25 veillard 533: /*
1.23 veillard 534: * Check for RPM files by looking at the suffix
1.22 veillard 535: */
1.25 veillard 536: else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm"))) {
1.35 veillard 537: cur = rpmOpen(filename, dir, tree);
1.44 veillard 538: }
539:
540: /*
541: * Check for RDF files by looking at the suffix
542: */
543: else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
544: cur = rpmOpenRdf(filename, dir, tree);
1.22 veillard 545: }
1.35 veillard 546:
1.22 veillard 547: /*
1.23 veillard 548: * Else if this is a directory, recurse !
1.22 veillard 549: */
1.25 veillard 550: else if (S_ISDIR(buf.st_mode)) {
551: if (filename[0] != '.') {
1.35 veillard 552: subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL);
553: cur = rpmOneDirScan(dir, subtree);
1.25 veillard 554: }
1.22 veillard 555: }
1.32 veillard 556: if (cur != NULL) ret = rpmAddList(ret, cur);
1.7 veillard 557: }
1.6 veillard 558: }
1.39 veillard 559: closedir(d);
1.33 veillard 560:
561: /*
562: * Dump the pages related to this directory.
563: */
1.35 veillard 564: if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36 veillard 565: else {
566: rpmRemoveSubdir(tree);
567: rpmFreeSubdir(tree);
568: }
1.35 veillard 569:
1.32 veillard 570: return(ret);
1.22 veillard 571: }
572:
573: /*
574: * Scan a directory for RPM files.
575: */
1.35 veillard 576: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37 veillard 577: rpmSubdirPtr cur;
578: rpmDataPtr ret;
579:
1.45 veillard 580: if ((rpm2html_dump_html) && (dir->build_tree != 0)) {
1.37 veillard 581: dir->root = rpmCreateRealRoot();
582: }
583: cur = rpmNewSubdir(tree, dir->name,
584: dir->subdir == NULL ? "" : dir->subdir, "", dir->color);
585: ret = rpmOneDirScan(dir, cur);
1.38 veillard 586: rpmDumpHtmlRealRoot(dir);
1.37 veillard 587: return(ret);
1.6 veillard 588: }
589:
590: /*
1.11 veillard 591: * Scan the local RPM database for RPM files.
592: */
1.32 veillard 593: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37 veillard 594: static char path[2000];
1.32 veillard 595: rpmDataPtr ret = NULL, cur;
1.11 veillard 596: rpmdb db;
597: Header h = NULL;
1.32 veillard 598: int offset;
1.11 veillard 599: char *prefix = "/";
600:
1.37 veillard 601: /*
602: * Create the directory for the HTML pages
603: */
1.45 veillard 604: if (rpm2html_dump_html) {
605: if (dir->subdir)
606: sprintf(path, "%s/%s", dir->dir, dir->subdir);
607: else
608: sprintf(path, "%s", dir->dir);
609: createDirectory(path);
610: }
611:
612: /*
613: * Create the directory for the RDF pages
614: */
615: if (rpm2html_rdf_dir != NULL) {
616: if (dir->subdir)
617: sprintf(path, "%s/%s", rpm2html_rdf_dir, dir->subdir);
618: else
619: sprintf(path, "%s", rpm2html_rdf_dir);
620: createDirectory(path);
621: }
1.37 veillard 622:
1.11 veillard 623: if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32 veillard 624: return(NULL);
1.11 veillard 625: }
626: offset = rpmdbFirstRecNum(db);
627: while (offset) {
628: h = rpmdbGetRecord(db, offset);
629: if (!h) {
630: fprintf(stderr, "could not read database record!\n");
1.32 veillard 631: return(ret);
1.11 veillard 632: }
1.36 veillard 633: cur = rpmAnalyze(NULL, h, dir, NULL, 0);
1.32 veillard 634: if (cur != NULL) ret = rpmAddList(ret, cur);
1.11 veillard 635: headerFree(h);
636: offset = rpmdbNextRecNum(db, offset);
637: }
638: rpmdbClose(db);
639:
1.32 veillard 640: return(ret);
1.11 veillard 641: }
642:
643: /*
1.6 veillard 644: * Scan all registered directories.
645: * One fist check for completeness of the informations in
646: * the rpmDir structure.
647: */
648:
1.32 veillard 649: rpmDataPtr rpmDirScanAll(void) {
1.18 veillard 650: rpmDirPtr dir, next;
1.32 veillard 651: rpmDataPtr ret = NULL, cur;
1.46 ! veillard 652: int maxLists = 50;
! 653: rpmDataPtr *rpmLists;
1.35 veillard 654: int nbLists = 0;
655: int i;
1.18 veillard 656:
657: /*
658: * first reverse the list ....
659: */
660: dir = dirList;
661: dirList = NULL;
662: while (dir != NULL) {
663: next = dir->next;
664: dir->next = dirList;
665: dirList = dir;
666: dir = next;
667: }
668:
1.35 veillard 669: /*
670: * Allocate a directory tree.
671: */
672: dirTree = rpmNewSubdir(NULL, "", "", "", NULL);
1.37 veillard 673:
1.18 veillard 674: dir = dirList;
1.6 veillard 675:
1.46 ! veillard 676: rpmLists = (rpmDataPtr *) malloc(maxLists * sizeof(rpmDataPtr));
! 677: if (rpmLists == NULL) {
! 678: fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
! 679: exit(1);
! 680: }
! 681:
1.6 veillard 682: while (dir != NULL) {
1.32 veillard 683: cur = NULL;
684:
1.14 veillard 685: /*
686: * Override default setting.
687: */
1.15 veillard 688: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
689: dir->maint = strdup(rpm2html_maint);
690: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
691: dir->mail = strdup(rpm2html_mail);
692: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
693: dir->ftp = strdup(rpm2html_ftp);
694: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
695: dir->ftpsrc = strdup(rpm2html_ftpsrc);
696: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
697: dir->dir = strdup(rpm2html_dir);
698: if ((dir->host == NULL) && (rpm2html_host != NULL))
699: dir->host = strdup(rpm2html_host);
700: if ((dir->name == NULL) && (rpm2html_name != NULL))
701: dir->name = strdup(rpm2html_name);
702: if ((dir->url == NULL) && (rpm2html_url != NULL))
703: dir->url = strdup(rpm2html_url);
1.14 veillard 704:
705: if (dir->rpmdir == NULL) {
1.6 veillard 706: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.14 veillard 707: } else if (!strcmp(dir->rpmdir, "localbase")) {
1.11 veillard 708: /* Scan the local RPM database instead of a directory */
1.32 veillard 709: cur = rpmBaseScan(dir);
1.7 veillard 710: } else if (dir->ftp == NULL) {
711: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14 veillard 712: dir->rpmdir);
1.6 veillard 713: } else {
1.16 veillard 714: if (verbose)
715: fprintf(stderr, "Scanning directory %s for RPMs\n",dir->rpmdir);
1.35 veillard 716: cur = rpmDirScan(dir, dirTree);
1.6 veillard 717: }
718:
1.35 veillard 719: if (cur != NULL) {
1.46 ! veillard 720: if (nbLists >= maxLists) {
! 721: maxLists *= 2;
! 722: rpmLists = (rpmDataPtr *) realloc(rpmLists,
! 723: maxLists * sizeof(rpmDataPtr));
! 724: if (rpmLists == NULL) {
! 725: fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
! 726: exit(1);
1.35 veillard 727: }
728: }
1.46 ! veillard 729: rpmLists[nbLists] = cur;
! 730: nbLists++;
1.39 veillard 731: }
732: if (dir->root != NULL) {
733: if (rpm2html_build_tree)
734: treeRoot = rpmMergeRealRoots(treeRoot, dir->root);
735: else
736: rpmDestroyRealRoot(dir->root);
1.35 veillard 737: }
1.32 veillard 738:
1.6 veillard 739: dir = dir->next;
740: }
1.35 veillard 741: for (i = 0;i < nbLists;i++)
742: ret = rpmAddList(ret, rpmLists[i]);
1.46 ! veillard 743: free(rpmLists);
1.32 veillard 744: return(ret);
1.1 veillard 745: }
746:
Webmaster