File:  [Public] / rpm2html / rpmopen.c
Revision 1.16: download - view: text, annotated - select for diffs
Tue Dec 16 14:47:24 1997 UTC (26 years, 5 months ago) by veillard
Branches: MAIN
CVS tags: VERSION_0_30, HEAD
Added verbose/silent flags, Daniel.

/*
 * rpmopen.c : open an extract informations from RPM files.
 *
 * Copyright (c) 1997 Daniel Veillard <veillard@apocalypse.org>
 * See COPYING for the status of this software.
 *
 * $Id: rpmopen.c,v 1.16 1997/12/16 14:47:24 veillard Exp $
 */

#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <dirent.h>
#include <errno.h>

#include <rpm/rpmlib.h>

#include "rpmdata.h"
#include "html.h"
#include "rpm2html.h"
#include "language.h"

/*
 * Get the internal number associated to an RPM tag.
 */
static int getTagNumber(char *tag) {
    int i;
    const struct headerTagTableEntry * t;

    for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
	if (!strcasecmp(tag, t->name)) return(t->val);
    }
    fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
    return(-1);
}

/*
 * rpmAnalyze : analyze an RPM record, read and parse the header and 
 *              fill the informations in the database.
 */
int rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir) {
    int installed = dir->installbase;
    char * name = NULL, * version = NULL, * release = NULL;
    int_32 count, type;
    void * p = NULL;
    int val, i, j;
    rpmDataPtr rpm = NULL;
    static char buffer[500000];
    static char nameBuffer[500];

    /* extract informations from the header */
    headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
    headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
    headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
        
    /* allocate a new rpmData block, fill it */
    rpm = (rpmDataPtr) malloc(sizeof(rpmData));
    memset(rpm, 0, sizeof(rpmData));
    if (rpm == NULL) {
         fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
	         strerror(errno));
         return(-1);
    }
    rpm->dir = dir;
    rpm->name = strdup(name);
    rpm->version = strdup(version);
    rpm->release = strdup(release);

    /* get all the ressources provided by this RPM */
    if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
        rpm->summary = localizedStrings[LANG_NO_SUMMARY];
    } else {
	rpm->summary = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p) {
        rpm->description = localizedStrings[LANG_NO_DESCRIPTION];
    } else {
	rpm->description = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p) {
        rpm->distribution = localizedStrings[LANG_UNKNOWN];
    } else {
	rpm->distribution = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p) {
        rpm->arch = localizedStrings[LANG_NONE];
	if (nameRpm == NULL) {
	    sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
	    nameRpm = nameBuffer;
	}
    } else {
	rpm->arch = strdup((char *) p);
	if (nameRpm == NULL) {
	    sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
	            name, version, release, (char *)p);
	    nameRpm = nameBuffer;
	}
    }
    if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p) {
        rpm->os = "";
    } else {
	rpm->os = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p) {
        rpm->vendor = NULL;
    } else {
	rpm->vendor = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p) {
        rpm->group = localizedStrings[LANG_NO_GROUP];
    } else {
	rpm->group = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p) {
        rpm->host = localizedStrings[LANG_NO_HOST];
    } else {
	rpm->host = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
        rpm->size = 0;
    } else {
	rpm->size = *((int *) p);
    }
    if (installed) {
	if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
	    rpm->date = 0;
	} else {
	    rpm->date = *((int_32 *) p);
	}
    } else {
	if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
	    rpm->date = 0;
	} else {
	    rpm->date = *((int_32 *) p);
	}
    }
    if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p) {
        rpm->srcrpm = "";
    } else {
	rpm->srcrpm = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p) {
        rpm->url = NULL;
    } else {
	rpm->url = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p) {
        rpm->packager = NULL;
    } else {
	rpm->packager = strdup((char *) p);
    }
    if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p) {
        rpm->copyright = NULL;
    } else {
	rpm->copyright = strdup((char *) p);
    }
    if (rpm->vendor == NULL) {
        if (rpm->packager != NULL) rpm->vendor = strdup(rpm->packager);
	else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
    }

    rpm->filename = strdup(nameRpm);

    /* package-xxx.rpm provides the ressource "package" */
    rpm->nb_ressources = 1;
    rpm->ressources[0] = rpmRessAdd(name, rpm, installed);

    val = getTagNumber("RPMTAG_PROVIDES");
    if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
        rpm->nb_ressources = 1;
    } else {
	if (count >= MAX_RESS) {
	    fprintf(stderr, "MAX_RESS %d overflow, increase the limit!\n",
		    MAX_RESS);
	    count = MAX_RESS;
	}

        for (i = 0, j = rpm->nb_ressources; i < count;j++, i++) {
	    rpm->ressources[j] = rpmRessAdd(((char **) p)[i], rpm, installed);
	}
	rpm->nb_ressources += count;
    }

    val = getTagNumber("RPMTAG_REQUIRENAME");
    if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
        rpm->nb_requires = 0;
    } else {
	if (count >= MAX_REQU) {
	    fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n",
		    MAX_REQU);
	    count = MAX_REQU;
	}

	rpm->nb_requires = count;
        for (i = 0; i < count;i++) {
	    rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed);
	}
    }
    val = getTagNumber("RPMTAG_FILENAMES");
    if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
        rpm->filelist = NULL; /* No filelist in the package ! */
    } else {
        char *ptr = buffer;
	for (i = 0; i < count;i++) {
	    ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
	}
	rpm->filelist = strdup(buffer);
    }

    /* insert the package informations in the database */
    if (installed) {
	rpm->next = rpmInstalledList;
	rpmInstalledList = rpm;
    } else {
	rpm->next = rpmList;
	rpmList = rpm;
    }

    /* dump the HTML related to this package */
    dumpRpmHtml(rpm);

    /* free large amount of data not used later */
    if (rpm->filelist) free(rpm->filelist);
    rpm->filelist = NULL;
    if (rpm->copyright) free(rpm->copyright);
    rpm->copyright = NULL;
    if (rpm->description) free(rpm->description);
    rpm->description = NULL;

    /* increment the counters */
    if (installed) {
	rpm2html_install_files++;
	rpm2html_install_size += rpm->size;
    } else {
	rpm2html_files++;
	rpm2html_size += rpm->size;
    }

    return(0);
}

/*
 * rpmOpen : open an RPM file, read and parse the header and 
 *           fill the informations in the database.
 */
int rpmOpen(char *nameRpm, rpmDirPtr dir) {
    int fd;
    int rc;
    int n;
    Header h = NULL;
    int isSource;
    char buffer[500];

    /* open the file for reading */
    sprintf(buffer, "%s/%s", dir->rpmdir, nameRpm);
    if ((fd = open(buffer, O_RDONLY)) < 0) {
         fprintf(stderr, "open of %s failed: %s\n", buffer,
	         strerror(errno));
	 return(-1);
    }

    /* read the RPM header */
    rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
    switch (rc) {
	case 0:
	    if (!h) {
		fprintf(stderr,
			"old format source packages cannot be queried\n");
		return(-1);
	    }
	    break;
	case 1:
	    fprintf(stderr, "%s does not appear to be a RPM package\n",
		    nameRpm);
	    return(-1);
	case 2:
	    fprintf(stderr, "query of %s failed\n", nameRpm);
	    return(-1);
	default:
	    fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
		    nameRpm, rc);
	    return(-1);
    }

    n = rpmAnalyze(nameRpm, h, dir);

    /* free the header and close the descriptor */
    headerFree(h);
    close(fd);

    return(n);
}

/*
 * Scan a directory for RPM files.
 */
static int rpmDirScan(rpmDirPtr dir) {
    struct dirent **namelist;
    char *filename;
    int len;
    int n, i;

    n = scandir(dir->rpmdir, &namelist, 0, alphasort);
    if (n < 0) {
        fprintf(stderr, "Listing of %s failed: %s\n", dir->rpmdir,
	        strerror(errno));
	return(-1);
    } else {
        for (i = 0;i < n;i++) {
	    /* check that this is a RPM file by looking at the suffix */
	    filename = namelist[i]->d_name;
	    len = strlen(filename);
	    if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm")))
	        rpmOpen(filename, dir);
	}
    }
    free(namelist);
    return(n);
}

/*
 * Scan the local RPM database for RPM files.
 */
static int rpmBaseScan(rpmDirPtr dir) {
    rpmdb db;
    Header h = NULL;
    int offset, n = 0;
    char *prefix = "/";

    if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
        return(n);
    }
    offset = rpmdbFirstRecNum(db);
    while (offset) {
        h = rpmdbGetRecord(db, offset);
	if (!h) {
	    fprintf(stderr, "could not read database record!\n");
	    return(n);
	}
	rpmAnalyze(NULL, h, dir);
	headerFree(h);
	offset = rpmdbNextRecNum(db, offset);
    }
    rpmdbClose(db);

    return(n);
}

/*
 * Scan all registered directories.
 * One fist check for completeness of the informations in
 * the rpmDir structure.
 */

int rpmDirScanAll(void) {
    int n = 0, i;

    rpmDirPtr dir = dirList;

    while (dir != NULL) {
	/*
	 * Override default setting.
	 */
	if ((dir->maint == NULL) && (rpm2html_maint != NULL))
	    dir->maint = strdup(rpm2html_maint);
	if ((dir->mail == NULL) && (rpm2html_mail != NULL))
	    dir->mail = strdup(rpm2html_mail);
	if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
	    dir->ftp = strdup(rpm2html_ftp);
	if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
	    dir->ftpsrc = strdup(rpm2html_ftpsrc);
	if ((dir->dir == NULL) && (rpm2html_dir != NULL))
	    dir->dir = strdup(rpm2html_dir);
	if ((dir->host == NULL) && (rpm2html_host != NULL))
	    dir->host = strdup(rpm2html_host);
	if ((dir->name == NULL) && (rpm2html_name != NULL))
	    dir->name = strdup(rpm2html_name);
	if ((dir->url == NULL) && (rpm2html_url != NULL))
	    dir->url = strdup(rpm2html_url);

        if (dir->rpmdir == NULL) {
	    fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
	} else if (!strcmp(dir->rpmdir, "localbase")) {
	    /* Scan the local RPM database instead of a directory */
            i = rpmBaseScan(dir);
	    if (i > 0) n += i;
	} else if (dir->ftp == NULL) {
	    fprintf(stderr, "Directory %s disabled : no ftp field\n",
	            dir->rpmdir);
	} else {
	    if (verbose)
		fprintf(stderr, "Scanning directory %s for RPMs\n",dir->rpmdir);
	    i = rpmDirScan(dir);
	    if (i > 0) n += i;
	}

        dir = dir->next;
    }
    return(n);
}


Webmaster