Annotation of rpm2html/rpmopen.c, revision 1.13
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.13 ! veillard 7: * $Id: rpmopen.c,v 1.12 1997/11/16 08:25:49 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.11 veillard 50: int rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir) {
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));
67: if (rpm == NULL) {
68: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
69: strerror(errno));
1.11 veillard 70: return(-1);
1.1 veillard 71: }
1.6 veillard 72: rpm->dir = dir;
1.1 veillard 73: rpm->name = strdup(name);
74: rpm->version = strdup(version);
75: rpm->release = strdup(release);
76:
77: /* get all the ressources provided by this RPM */
1.2 veillard 78: if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.12 veillard 79: rpm->summary = localizedStrings[LANG_NO_SUMMARY];
1.2 veillard 80: } else {
81: rpm->summary = strdup((char *) p);
82: }
83: if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p) {
1.12 veillard 84: rpm->description = localizedStrings[LANG_NO_DESCRIPTION];
1.2 veillard 85: } else {
86: rpm->description = strdup((char *) p);
87: }
88: if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p) {
1.12 veillard 89: rpm->distribution = localizedStrings[LANG_UNKNOWN];
1.2 veillard 90: } else {
91: rpm->distribution = strdup((char *) p);
92: }
93: if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p) {
1.12 veillard 94: rpm->arch = localizedStrings[LANG_NONE];
1.11 veillard 95: if (nameRpm == NULL) {
1.12 veillard 96: sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
1.11 veillard 97: nameRpm = nameBuffer;
98: }
1.2 veillard 99: } else {
100: rpm->arch = strdup((char *) p);
1.11 veillard 101: if (nameRpm == NULL) {
1.12 veillard 102: sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
103: name, version, release, (char *)p);
1.11 veillard 104: nameRpm = nameBuffer;
105: }
1.2 veillard 106: }
1.7 veillard 107: if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p) {
108: rpm->os = "";
109: } else {
110: rpm->os = strdup((char *) p);
111: }
1.2 veillard 112: if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p) {
1.7 veillard 113: rpm->vendor = NULL;
1.2 veillard 114: } else {
115: rpm->vendor = strdup((char *) p);
116: }
117: if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p) {
1.12 veillard 118: rpm->group = localizedStrings[LANG_NO_GROUP];
1.2 veillard 119: } else {
120: rpm->group = strdup((char *) p);
121: }
122: if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p) {
1.12 veillard 123: rpm->host = localizedStrings[LANG_NO_HOST];
1.2 veillard 124: } else {
125: rpm->host = strdup((char *) p);
126: }
127: if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
128: rpm->size = 0;
129: } else {
130: rpm->size = *((int *) p);
131: }
1.11 veillard 132: if (installed) {
133: if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
134: rpm->date = 0;
135: } else {
136: rpm->date = *((int_32 *) p);
137: }
1.2 veillard 138: } else {
1.11 veillard 139: if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
140: rpm->date = 0;
141: } else {
142: rpm->date = *((int_32 *) p);
143: }
1.2 veillard 144: }
145: if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p) {
146: rpm->srcrpm = "";
147: } else {
148: rpm->srcrpm = strdup((char *) p);
149: }
1.7 veillard 150: if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p) {
151: rpm->url = NULL;
152: } else {
153: rpm->url = strdup((char *) p);
154: }
155: if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p) {
156: rpm->packager = NULL;
157: } else {
158: rpm->packager = strdup((char *) p);
159: }
160: if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p) {
161: rpm->copyright = NULL;
162: } else {
163: rpm->copyright = strdup((char *) p);
164: }
165: if (rpm->vendor == NULL) {
166: if (rpm->packager != NULL) rpm->vendor = rpm->packager;
1.12 veillard 167: else rpm->vendor = localizedStrings[LANG_UNKNOWN];
1.7 veillard 168: }
1.2 veillard 169:
1.11 veillard 170: rpm->filename = strdup(nameRpm);
171:
1.10 veillard 172: /* package-xxx.rpm provides the ressource "package" */
173: rpm->nb_ressources = 1;
1.11 veillard 174: rpm->ressources[0] = rpmRessAdd(name, rpm, installed);
1.10 veillard 175:
1.1 veillard 176: val = getTagNumber("RPMTAG_PROVIDES");
177: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.10 veillard 178: rpm->nb_ressources = 1;
1.1 veillard 179: } else {
180: if (count >= MAX_RESS) {
181: fprintf(stderr, "MAX_RESS %d overflow, increase the limit!\n",
182: MAX_RESS);
183: count = MAX_RESS;
184: }
185:
1.10 veillard 186: for (i = 0, j = rpm->nb_ressources; i < count;j++, i++) {
1.11 veillard 187: rpm->ressources[j] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4 veillard 188: }
1.10 veillard 189: rpm->nb_ressources += count;
1.4 veillard 190: }
191:
192: val = getTagNumber("RPMTAG_REQUIRENAME");
193: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
194: rpm->nb_requires = 0;
195: } else {
196: if (count >= MAX_REQU) {
197: fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n",
198: MAX_REQU);
199: count = MAX_REQU;
200: }
201:
202: rpm->nb_requires = count;
203: for (i = 0; i < count;i++) {
1.11 veillard 204: rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed);
1.1 veillard 205: }
1.5 veillard 206: }
207: val = getTagNumber("RPMTAG_FILENAMES");
208: if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.7 veillard 209: rpm->filelist = NULL; /* No filelist in the package ! */
1.5 veillard 210: } else {
211: char *ptr = buffer;
212: for (i = 0; i < count;i++) {
213: ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
214: }
215: rpm->filelist = strdup(buffer);
1.1 veillard 216: }
217:
218: /* insert the package informations in the database */
1.11 veillard 219: if (installed) {
220: rpm->next = rpmInstalledList;
221: rpmInstalledList = rpm;
222: } else {
223: rpm->next = rpmList;
224: rpmList = rpm;
225: }
1.7 veillard 226:
227: /* dump the HTML related to this package */
228: dumpRpmHtml(rpm);
229:
230: /* free large amount of data not used later */
231: if (rpm->filelist) free(rpm->filelist);
232: if (rpm->copyright) free(rpm->copyright);
1.8 veillard 233:
234: /* increment the counters */
1.11 veillard 235: if (installed) {
236: rpm2html_install_files++;
237: rpm2html_install_size += rpm->size;
238: } else {
239: rpm2html_files++;
240: rpm2html_size += rpm->size;
241: }
1.7 veillard 242:
1.1 veillard 243: return(0);
1.11 veillard 244: }
245:
246: /*
247: * rpmOpen : open an RPM file, read and parse the header and
248: * fill the informations in the database.
249: */
250: int rpmOpen(char *nameRpm, rpmDirPtr dir) {
251: int fd;
252: int rc;
253: int n;
254: Header h = NULL;
255: int isSource;
256: char buffer[500];
257:
258: /* open the file for reading */
259: sprintf(buffer, "%s/%s", dir->dir, nameRpm);
260: if ((fd = open(buffer, O_RDONLY)) < 0) {
261: fprintf(stderr, "open of %s failed: %s\n", buffer,
262: strerror(errno));
263: return(-1);
264: }
265:
266: /* read the RPM header */
267: rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
268: switch (rc) {
269: case 0:
270: if (!h) {
271: fprintf(stderr,
272: "old format source packages cannot be queried\n");
273: return(-1);
274: }
275: break;
276: case 1:
277: fprintf(stderr, "%s does not appear to be a RPM package\n",
278: nameRpm);
279: return(-1);
280: case 2:
281: fprintf(stderr, "query of %s failed\n", nameRpm);
282: return(-1);
283: default:
284: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
285: nameRpm, rc);
286: return(-1);
287: }
288:
289: n = rpmAnalyze(nameRpm, h, dir);
290:
291: /* free the header and close the descriptor */
292: headerFree(h);
293: close(fd);
1.1 veillard 294:
1.11 veillard 295: return(n);
1.6 veillard 296: }
297:
298: /*
299: * Scan a directory for RPM files.
300: */
301: static int rpmDirScan(rpmDirPtr dir) {
302: struct dirent **namelist;
1.7 veillard 303: char *filename;
304: int len;
1.6 veillard 305: int n, i;
306:
307: n = scandir(dir->dir, &namelist, 0, alphasort);
308: if (n < 0) {
309: fprintf(stderr, "Listing of %s failed: %s\n", dir->dir,
310: strerror(errno));
311: return(-1);
312: } else {
1.7 veillard 313: for (i = 0;i < n;i++) {
314: /* check that this is a RPM file by looking at the suffix */
315: filename = namelist[i]->d_name;
316: len = strlen(filename);
317: if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm")))
318: rpmOpen(filename, dir);
319: }
1.6 veillard 320: }
321: free(namelist);
322: return(n);
323: }
324:
325: /*
1.11 veillard 326: * Scan the local RPM database for RPM files.
327: */
328: static int rpmBaseScan(rpmDirPtr dir) {
329: rpmdb db;
330: Header h = NULL;
331: int offset, n = 0;
332: char *prefix = "/";
333:
334: if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
335: return(n);
336: }
337: offset = rpmdbFirstRecNum(db);
338: while (offset) {
339: h = rpmdbGetRecord(db, offset);
340: if (!h) {
341: fprintf(stderr, "could not read database record!\n");
342: return(n);
343: }
344: rpmAnalyze(NULL, h, dir);
345: headerFree(h);
346: offset = rpmdbNextRecNum(db, offset);
347: }
348: rpmdbClose(db);
349:
350: return(n);
351: }
352:
353: /*
1.6 veillard 354: * Scan all registered directories.
355: * One fist check for completeness of the informations in
356: * the rpmDir structure.
357: */
358:
359: int rpmDirScanAll(void) {
1.7 veillard 360: int n = 0, i;
361:
1.6 veillard 362: rpmDirPtr dir = dirList;
363:
364: while (dir != NULL) {
365: if (dir->dir == NULL) {
366: fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.11 veillard 367: }
368:
369: if (!strcmp(dir->dir, "localbase")) {
370: /* Scan the local RPM database instead of a directory */
371: i = rpmBaseScan(dir);
372: if (i > 0) n += i;
1.7 veillard 373: } else if (dir->ftp == NULL) {
374: fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.6 veillard 375: dir->dir);
1.7 veillard 376: } else if (dir->nb_urls <= 0) {
1.6 veillard 377: fprintf(stderr, "Directory %s disabled : no url(s) field\n",
378: dir->dir);
379: } else {
380: fprintf(stderr, "Scanning directory %s for RPMs\n", dir->dir);
1.7 veillard 381: i = rpmDirScan(dir);
382: if (i > 0) n += i;
1.6 veillard 383: }
384:
385: dir = dir->next;
386: }
1.7 veillard 387: return(n);
1.1 veillard 388: }
389:
Webmaster