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