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