Blame lib/rpmlead.c

2ff057
/** \ingroup lead
2ff057
 * \file lib/rpmlead.c
2ff057
 */
2ff057
2ff057
#include "system.h"
2ff057
2ff057
#include <errno.h>
2ff057
#include <netinet/in.h>
2ff057
2ff057
#include <rpm/rpmlib.h>		/* rpmGetOs/ArchInfo() */
2ff057
#include <rpm/rpmlog.h>
2ff057
#include <rpm/rpmstring.h>
2ff057
2ff057
#include "lib/signature.h"
2ff057
#include "lib/header_internal.h"	/* Freadall() */
2ff057
#include "lib/rpmlead.h"
2ff057
2ff057
#include "debug.h"
2ff057
2ff057
/* A long time ago in a galaxy far far away, signatures were not in a header */
2ff057
#define RPMSIGTYPE_HEADERSIG 5
2ff057
2ff057
static unsigned char const lead_magic[] = {
2ff057
    RPMLEAD_MAGIC0, RPMLEAD_MAGIC1, RPMLEAD_MAGIC2, RPMLEAD_MAGIC3
2ff057
};
2ff057
2ff057
/** \ingroup lead
2ff057
 * The lead data structure.
2ff057
 * The lead needs to be 8 byte aligned.
2ff057
 * @deprecated The lead (except for signature_type) is legacy.
2ff057
 * @todo Don't use any information from lead.
2ff057
 */
2ff057
struct rpmlead_s {
2ff057
    unsigned char magic[4];
2ff057
    unsigned char major;
2ff057
    unsigned char minor;
2ff057
    short type;
2ff057
    short archnum;
2ff057
    char name[66];
2ff057
    short osnum;
2ff057
    short signature_type;       /*!< Signature header type (RPMSIG_HEADERSIG) */
2ff057
    char reserved[16];      /*!< Pad to 96 bytes -- 8 byte aligned! */
2ff057
};
2ff057
2ff057
static int rpmLeadFromHeader(Header h, struct rpmlead_s *l)
2ff057
{
2ff057
    if (h != NULL) {
2ff057
	int archnum, osnum;
2ff057
	char * nevr = headerGetAsString(h, RPMTAG_NEVR);
2ff057
2ff057
	/* FIXME: should grab these from header instead (RhBug:717898) */
2ff057
	rpmGetArchInfo(NULL, &archnum);
2ff057
	rpmGetOsInfo(NULL, &osnum);
2ff057
2ff057
	memset(l, 0, sizeof(*l));
2ff057
	l->major = 3;
2ff057
	l->minor = 0;
2ff057
	l->archnum = archnum;
2ff057
	l->osnum = osnum;
2ff057
	l->signature_type = RPMSIGTYPE_HEADERSIG;
2ff057
	l->type = (headerIsSource(h) ? 1 : 0);
2ff057
2ff057
	memcpy(l->magic, lead_magic, sizeof(l->magic));
2ff057
	rstrlcpy(l->name, nevr, sizeof(l->name));
2ff057
2ff057
	free(nevr);
2ff057
    }
2ff057
2ff057
    return (h != NULL);
2ff057
}
2ff057
2ff057
/* The lead needs to be 8 byte aligned */
2ff057
rpmRC rpmLeadWrite(FD_t fd, Header h)
2ff057
{
2ff057
    rpmRC rc = RPMRC_FAIL;
2ff057
    struct rpmlead_s l;
2ff057
2ff057
    if (rpmLeadFromHeader(h, &l)) {
2ff057
	
2ff057
	l.type = htons(l.type);
2ff057
	l.archnum = htons(l.archnum);
2ff057
	l.osnum = htons(l.osnum);
2ff057
	l.signature_type = htons(l.signature_type);
2ff057
	    
2ff057
	if (Fwrite(&l, 1, sizeof(l), fd) == sizeof(l))
2ff057
	    rc = RPMRC_OK;
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static rpmRC rpmLeadCheck(struct rpmlead_s *lead, char **msg)
2ff057
{
2ff057
    if (memcmp(lead->magic, lead_magic, sizeof(lead_magic))) {
2ff057
	*msg = xstrdup(_("not an rpm package"));
2ff057
	return RPMRC_NOTFOUND;
2ff057
    }
2ff057
    if (lead->signature_type != RPMSIGTYPE_HEADERSIG) {
2ff057
	*msg = xstrdup(_("illegal signature type"));
2ff057
	return RPMRC_FAIL;
2ff057
    }
2ff057
    if (lead->major < 3 || lead->major > 4) {
2ff057
	*msg = xstrdup(_("unsupported RPM package version"));
2ff057
	return RPMRC_FAIL;
2ff057
    }
2ff057
    return RPMRC_OK;
2ff057
}
2ff057
2ff057
rpmRC rpmLeadRead(FD_t fd, char **emsg)
2ff057
{
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
    struct rpmlead_s l;
2ff057
    char *err = NULL;
2ff057
2ff057
    memset(&l, 0, sizeof(l));
2ff057
    if (Freadall(fd, &l, sizeof(l)) != sizeof(l)) {
2ff057
	if (Ferror(fd)) {
2ff057
	    rasprintf(&err, _("read failed: %s (%d)\n"), Fstrerror(fd), errno);
2ff057
	    rc = RPMRC_FAIL;
2ff057
	} else {
2ff057
	    err = xstrdup(_("not an rpm package\n"));
2ff057
	    rc = RPMRC_NOTFOUND;
2ff057
	}
2ff057
    } else {
2ff057
	l.type = ntohs(l.type);
2ff057
	l.archnum = ntohs(l.archnum);
2ff057
	l.osnum = ntohs(l.osnum);
2ff057
	l.signature_type = ntohs(l.signature_type);
2ff057
	rc = rpmLeadCheck(&l, &err;;
2ff057
    }
2ff057
2ff057
    if (rc != RPMRC_OK) {
2ff057
	if (emsg != NULL)
2ff057
	    *emsg = err;
2ff057
	else
2ff057
	    free(err);
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}