Annotation of rpm2html/rpmopen.c, revision 1.20
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.20 ! veillard 7: * $Id: rpmopen.c,v 1.19 1998/01/10 03:52:20 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.1 veillard 24:
25: #include <rpm/rpmlib.h>
26:
27: #include "rpmdata.h"
1.7 veillard 28: #include "html.h"
1.8 veillard 29: #include "rpm2html.h"
1.12 veillard 30: #include "language.h"
1.1 veillard 31:
32: /*
33: * Get the internal number associated to an RPM tag.
34: */
35: static int getTagNumber(char *tag) {
36: int i;
37: const struct headerTagTableEntry * t;
38:
39: for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
40: if (!strcasecmp(tag, t->name)) return(t->val);
41: }
42: fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
43: return(-1);
44: }
45:
46: /*
1.11 veillard 47: * rpmAnalyze : analyze an RPM record, read and parse the header and
48: * fill the informations in the database.
1.1 veillard 49: */
1.20 ! veillard 50: int rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir, time_t stamp) {
1.11 veillard 51: int installed = dir->installbase;
1.2 veillard 52: char * name = NULL, * version = NULL, * release = NULL;
1.1 veillard 53: int_32 count, type;
1.2 veillard 54: void * p = NULL;
1.10 veillard 55: int val, i, j;
1.1 veillard 56: rpmDataPtr rpm = NULL;
1.5 veillard 57: static char buffer[500000];
1.11 veillard 58: static char nameBuffer[500];
1.1 veillard 59:
60: /* extract informations from the header */
61: headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
62: headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
63: headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
64:
65: /* allocate a new rpmData block, fill it */
66: rpm = (rpmDataPtr) malloc(sizeof(rpmData));
1.15 veillard 67: memset(rpm, 0, sizeof(rpmData));
1.1 veillard 68: if (rpm == NULL) {
69: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
70: strerror(errno));
1.11 veillard 71: return(-1);
1.1 veillard 72: }
1.6 veillard 73: rpm->dir = dir;
1.20 ! veillard 74: rpm->stamp = stamp;
1.1 veillard 75: rpm->name = strdup(name);
76: rpm->version = strdup(version);
77: rpm->release = strdup(release);
78:
79: /* get all the ressources provided by this RPM */
1.2 veillard 80: if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.12 veillard 81: rpm->summary = localizedStrings[LANG_NO_SUMMARY];
1.2 veillard 82: } else {
1.19 veillard 83: rpm->summary = strdupHTML((char *) p);
1.2 veillard 84: }
85: if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p) {
1.12 veillard 86: rpm->description = localizedStrings[LANG_NO_DESCRIPTION];
1.2 veillard 87: } else {
1.19 veillard 88: rpm->description = strdupHTML((char *) p);
1.2 veillard 89: }
90: if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p) {
1.12 veillard 91: rpm->distribution = localizedStrings[LANG_UNKNOWN];
1.2 veillard 92: } else {
93: rpm->distribution = strdup((char *) p);
94: }
95: if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p) {
1.12 veillard 96: rpm->arch = localizedStrings[LANG_NONE];
1.11 veillard 97: if (nameRpm == NULL) {
1.12 veillard 98: sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
1.11 veillard 99: nameRpm = nameBuffer;
100: }
1.2 veillard 101: } else {
102: rpm->arch = strdup((char *) p);
1.11 veillard 103: if (nameRpm == NULL) {
1.12 veillard 104: sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
105: name, version, release, (char *)p);
1.11 veillard 106: nameRpm = nameBuffer;
107: }
1.2 veillard 108: }
1.7 veillard 109: if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p) {
110: rpm->os = "";
111: } else {
112: rpm->os = strdup((char *) p);
113: }
1.2 veillard 114: if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p) {
1.7 veillard 115: rpm->vendor = NULL;
1.2 veillard 116: } else {
117: rpm->vendor = strdup((char *) p);
118: }
119: if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p) {
1.12 veillard 120: rpm->group = localizedStrings[LANG_NO_GROUP];
1.2 veillard 121: } else {
122: rpm->group = strdup((char *) p);
123: }
124: if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p) {
1.12 veillard 125: rpm->host = localizedStrings[LANG_NO_HOST];
1.2 veillard 126: } else {
127: rpm->host = strdup((char *) p);
128: }
129: if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
130: rpm->size = 0;
131: } else {
132: rpm->size = *((int *) p);
133: }
1.11 veillard 134: if (installed) {
135: if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
136: rpm->date = 0;
137: } else {
138: rpm->date = *((int_32 *) p);
139: }
1.2 veillard 140: } else {
1.11 veillard 141: if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
142: rpm->date = 0;
143: } else {
144: rpm->date = *((int_32 *) p);
145: }
1.2 veillard 146: }
147: if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p) {
148: rpm->srcrpm = "";
149: } else {
150: rpm->srcrpm = strdup((char *) p);
151: }
1.7 veillard 152: if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p) {
153: rpm->url = NULL;
154: } else {
155: rpm->url = strdup((char *) p);
156: }
157: if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p) {
158: rpm->packager = NULL;
159: } else {
160: rpm->packager = strdup((char *) p);
161: }
162: if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p) {
163: rpm->copyright = NULL;
164: } else {
165: rpm->copyright = strdup((char *) p);
166: }
167: if (rpm->vendor == NULL) {
1.15 veillard 168: if (rpm->packager != NULL) rpm->vendor = strdup(rpm->packager);
169: else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
1.7 veillard 170: }
1.2 veillard 171:
1.11 veillard 172: rpm->filename = strdup(nameRpm);
173:
1.10 veillard 174: /* package-xxx.rpm provides the ressource "package" */
175: rpm->nb_ressources = 1;
1.11 veillard 176: rpm->ressources[0] = rpmRessAdd(name, rpm, installed);
1.10 veillard 177:
1.1 veillard 178: val = getTagNumber("RPMTAG_PROVIDES");
179: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.10 veillard 180: rpm->nb_ressources = 1;
1.1 veillard 181: } else {
182: if (count >= MAX_RESS) {
183: fprintf(stderr, "MAX_RESS %d overflow, increase the limit!\n",
184: MAX_RESS);
185: count = MAX_RESS;
186: }
187:
1.10 veillard 188: for (i = 0, j = rpm->nb_ressources; i < count;j++, i++) {
1.11 veillard 189: rpm->ressources[j] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4 veillard 190: }
1.10 veillard 191: rpm->nb_ressources += count;
1.4 veillard 192: }
193:
194: val = getTagNumber("RPMTAG_REQUIRENAME");
195: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
196: rpm->nb_requires = 0;
197: } else {
198: if (count >= MAX_REQU) {
199: fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n",
200: MAX_REQU);
201: count = MAX_REQU;
202: }
203:
204: rpm->nb_requires = count;
205: for (i = 0; i < count;i++) {
1.11 veillard 206: rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed);
1.1 veillard 207: }
1.5 veillard 208: }
209: val = getTagNumber("RPMTAG_FILENAMES");
210: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.7 veillard 211: rpm->filelist = NULL; /* No filelist in the package ! */
1.5 veillard 212: } else {
213: char *ptr = buffer;
214: for (i = 0; i < count;i++) {
215: ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
216: }
217: rpm->filelist = strdup(buffer);
1.1 veillard 218: }
219:
220: /* insert the package informations in the database */
1.11 veillard 221: if (installed) {
222: rpm->next = rpmInstalledList;
223: rpmInstalledList = rpm;
224: } else {
225: rpm->next = rpmList;
226: rpmList = rpm;
227: }
1.17 veillard 228:
229: /* Register this package */
230: rpmAddSoftware(rpm);
1.7 veillard 231:
232: /* dump the HTML related to this package */
233: dumpRpmHtml(rpm);
234:
235: /* free large amount of data not used later */
236: if (rpm->filelist) free(rpm->filelist);
1.15 veillard 237: rpm->filelist = NULL;
1.7 veillard 238: if (rpm->copyright) free(rpm->copyright);
1.15 veillard 239: rpm->copyright = NULL;
240: if (rpm->description) free(rpm->description);
241: rpm->description = NULL;
1.8 veillard 242:
243: /* increment the counters */
1.11 veillard 244: if (installed) {
245: rpm2html_install_files++;
246: rpm2html_install_size += rpm->size;
247: } else {
248: rpm2html_files++;
249: rpm2html_size += rpm->size;
250: }
1.7 veillard 251:
1.1 veillard 252: return(0);
1.11 veillard 253: }
254:
255: /*
256: * rpmOpen : open an RPM file, read and parse the header and
257: * fill the informations in the database.
258: */
259: int rpmOpen(char *nameRpm, rpmDirPtr dir) {
260: int fd;
261: int rc;
262: int n;
263: Header h = NULL;
264: int isSource;
265: char buffer[500];
1.20 ! veillard 266: struct stat buf;
1.11 veillard 267:
268: /* open the file for reading */
1.14 veillard 269: sprintf(buffer, "%s/%s", dir->rpmdir, nameRpm);
1.11 veillard 270: if ((fd = open(buffer, O_RDONLY)) < 0) {
271: fprintf(stderr, "open of %s failed: %s\n", buffer,
272: strerror(errno));
273: return(-1);
274: }
275:
1.20 ! veillard 276: stat(buffer, &buf);
! 277:
1.11 veillard 278: /* read the RPM header */
279: rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
280: switch (rc) {
281: case 0:
282: if (!h) {
283: fprintf(stderr,
284: "old format source packages cannot be queried\n");
285: return(-1);
286: }
287: break;
288: case 1:
289: fprintf(stderr, "%s does not appear to be a RPM package\n",
290: nameRpm);
291: return(-1);
292: case 2:
293: fprintf(stderr, "query of %s failed\n", nameRpm);
294: return(-1);
295: default:
296: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
297: nameRpm, rc);
298: return(-1);
299: }
300:
1.20 ! veillard 301: n = rpmAnalyze(nameRpm, h, dir, buf.st_mtime);
1.11 veillard 302:
303: /* free the header and close the descriptor */
304: headerFree(h);
305: close(fd);
1.1 veillard 306:
1.11 veillard 307: return(n);
1.6 veillard 308: }
309:
310: /*
311: * Scan a directory for RPM files.
312: */
313: static int rpmDirScan(rpmDirPtr dir) {
314: struct dirent **namelist;
1.7 veillard 315: char *filename;
316: int len;
1.6 veillard 317: int n, i;
318:
1.14 veillard 319: n = scandir(dir->rpmdir, &namelist, 0, alphasort);
1.6 veillard 320: if (n < 0) {
1.14 veillard 321: fprintf(stderr, "Listing of %s failed: %s\n", dir->rpmdir,
1.6 veillard 322: strerror(errno));
323: return(-1);
324: } else {
1.7 veillard 325: for (i = 0;i < n;i++) {
326: /* check that this is a RPM file by looking at the suffix */
327: filename = namelist[i]->d_name;
328: len = strlen(filename);
329: if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm")))
330: rpmOpen(filename, dir);
331: }
1.6 veillard 332: }
333: free(namelist);
334: return(n);
335: }
336:
337: /*
1.11 veillard 338: * Scan the local RPM database for RPM files.
339: */
340: static int rpmBaseScan(rpmDirPtr dir) {
341: rpmdb db;
342: Header h = NULL;
343: int offset, n = 0;
344: char *prefix = "/";
345:
346: if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
347: return(n);
348: }
349: offset = rpmdbFirstRecNum(db);
350: while (offset) {
351: h = rpmdbGetRecord(db, offset);
352: if (!h) {
353: fprintf(stderr, "could not read database record!\n");
354: return(n);
355: }
1.20 ! veillard 356: rpmAnalyze(NULL, h, dir, 0);
1.11 veillard 357: headerFree(h);
358: offset = rpmdbNextRecNum(db, offset);
359: }
360: rpmdbClose(db);
361:
362: return(n);
363: }
364:
365: /*
1.6 veillard 366: * Scan all registered directories.
367: * One fist check for completeness of the informations in
368: * the rpmDir structure.
369: */
370:
371: int rpmDirScanAll(void) {
1.7 veillard 372: int n = 0, i;
373:
1.18 veillard 374: rpmDirPtr dir, next;
375:
376: /*
377: * first reverse the list ....
378: */
379: dir = dirList;
380: dirList = NULL;
381: while (dir != NULL) {
382: next = dir->next;
383: dir->next = dirList;
384: dirList = dir;
385: dir = next;
386: }
387:
388: dir = dirList;
1.6 veillard 389:
390: while (dir != NULL) {
1.14 veillard 391: /*
392: * Override default setting.
393: */
1.15 veillard 394: if ((dir->maint == NULL) && (rpm2html_maint != NULL))
395: dir->maint = strdup(rpm2html_maint);
396: if ((dir->mail == NULL) && (rpm2html_mail != NULL))
397: dir->mail = strdup(rpm2html_mail);
398: if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
399: dir->ftp = strdup(rpm2html_ftp);
400: if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
401: dir->ftpsrc = strdup(rpm2html_ftpsrc);
402: if ((dir->dir == NULL) && (rpm2html_dir != NULL))
403: dir->dir = strdup(rpm2html_dir);
404: if ((dir->host == NULL) && (rpm2html_host != NULL))
405: dir->host = strdup(rpm2html_host);
406: if ((dir->name == NULL) && (rpm2html_name != NULL))
407: dir->name = strdup(rpm2html_name);
408: if ((dir->url == NULL) && (rpm2html_url != NULL))
409: dir->url = strdup(rpm2html_url);
1.14 veillard 410:
411: if (dir->rpmdir == NULL) {
1.6 veillard 412: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.14 veillard 413: } else if (!strcmp(dir->rpmdir, "localbase")) {
1.11 veillard 414: /* Scan the local RPM database instead of a directory */
415: i = rpmBaseScan(dir);
416: if (i > 0) n += i;
1.7 veillard 417: } else if (dir->ftp == NULL) {
418: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14 veillard 419: dir->rpmdir);
1.6 veillard 420: } else {
1.16 veillard 421: if (verbose)
422: fprintf(stderr, "Scanning directory %s for RPMs\n",dir->rpmdir);
1.7 veillard 423: i = rpmDirScan(dir);
424: if (i > 0) n += i;
1.6 veillard 425: }
426:
427: dir = dir->next;
428: }
1.7 veillard 429: return(n);
1.1 veillard 430: }
431:
Webmaster