csomh / source-git / rpm

Forked from source-git/rpm 4 years ago
Clone
2ff057
#include "system.h"
2ff057
2ff057
#include <rpm/rpmtd.h>
2ff057
#include <rpm/rpmstring.h>
2ff057
#include <rpm/rpmpgp.h>
2ff057
#include <rpm/rpmstrpool.h>
2ff057
#include "lib/misc.h"		/* format function prototypes */
2ff057
2ff057
#include "debug.h"
2ff057
2ff057
rpmtd rpmtdNew(void)
2ff057
{
2ff057
    rpmtd td = xmalloc(sizeof(*td));
2ff057
    rpmtdReset(td);
2ff057
    return td;
2ff057
}
2ff057
2ff057
rpmtd rpmtdFree(rpmtd td)
2ff057
{
2ff057
    /* permit free on NULL td */
2ff057
    if (td != NULL) {
2ff057
	rpmtdFreeData(td);
2ff057
	free(td);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
void rpmtdReset(rpmtd td)
2ff057
{
2ff057
    if (td) {
2ff057
	memset(td, 0, sizeof(*td));
2ff057
	td->ix = -1;
2ff057
    }
2ff057
}
2ff057
2ff057
void rpmtdFreeData(rpmtd td)
2ff057
{
2ff057
    if (td && td->data && td->flags & RPMTD_ALLOCED) {
2ff057
	if (td->flags & RPMTD_PTR_ALLOCED) {
2ff057
	    char **data = td->data;
2ff057
	    for (int i = 0; i < td->count; i++) {
2ff057
		free(data[i]);
2ff057
	    }
2ff057
	}
2ff057
	free(td->data);
2ff057
    }
2ff057
    rpmtdReset(td);
2ff057
}
2ff057
2ff057
rpm_count_t rpmtdCount(rpmtd td)
2ff057
{
2ff057
    rpm_count_t count = 0;
2ff057
    if (td != NULL) {
2ff057
	/* fix up for binary type abusing count as data length */
2ff057
	count = (td->type == RPM_BIN_TYPE) ? 1 : td->count;
2ff057
    }
2ff057
    return count;
2ff057
}
2ff057
2ff057
rpm_count_t rpmtdSize(rpmtd td)
2ff057
{
2ff057
    return (td != NULL) ? td->size : 0;
2ff057
}
2ff057
2ff057
rpmTagVal rpmtdTag(rpmtd td)
2ff057
{
2ff057
    return (td != NULL) ? td->tag : 0;
2ff057
}
2ff057
2ff057
rpmTagType rpmtdType(rpmtd td)
2ff057
{
2ff057
    return (td != NULL) ? td->type : 0;
2ff057
}
2ff057
2ff057
rpmTagClass rpmtdClass(rpmtd td)
2ff057
{
2ff057
    return (td != NULL) ? rpmTagTypeGetClass(td->type) : 0;
2ff057
}
2ff057
2ff057
rpmtdFlags rpmtdGetFlags(rpmtd td)
2ff057
{
2ff057
    return (td != NULL) ? td->flags : 0;
2ff057
}
2ff057
2ff057
int rpmtdGetIndex(rpmtd td)
2ff057
{
2ff057
    return (td != NULL) ? td->ix : -1;
2ff057
}
2ff057
2ff057
int rpmtdSetIndex(rpmtd td, int index)
2ff057
{
2ff057
    if (td == NULL || index < 0 || index >= rpmtdCount(td)) {
2ff057
	return -1;
2ff057
    }
2ff057
    td->ix = index;
2ff057
    return td->ix;
2ff057
}
2ff057
2ff057
int rpmtdInit(rpmtd td)
2ff057
{
2ff057
    if (td == NULL)
2ff057
	return -1;
2ff057
2ff057
    /* XXX check that this is an array type? */
2ff057
    td->ix = -1;
2ff057
    return 0;
2ff057
}
2ff057
2ff057
int rpmtdNext(rpmtd td)
2ff057
{
2ff057
    int i = -1;
2ff057
    
2ff057
    if (td != NULL && ++td->ix >= 0) {
2ff057
	if (td->ix < rpmtdCount(td)) {
2ff057
	    i = td->ix;
2ff057
	} else {
2ff057
	    td->ix = i;
2ff057
	}
2ff057
    }
2ff057
    return i;
2ff057
}
2ff057
2ff057
uint32_t *rpmtdNextUint32(rpmtd td)
2ff057
{
2ff057
    uint32_t *res = NULL;
2ff057
    if (rpmtdNext(td) >= 0) {
2ff057
	res = rpmtdGetUint32(td);
2ff057
    }
2ff057
    return res;
2ff057
}
2ff057
2ff057
uint64_t *rpmtdNextUint64(rpmtd td)
2ff057
{
2ff057
    uint64_t *res = NULL;
2ff057
    if (rpmtdNext(td) >= 0) {
2ff057
	res = rpmtdGetUint64(td);
2ff057
    }
2ff057
    return res;
2ff057
}
2ff057
2ff057
const char *rpmtdNextString(rpmtd td)
2ff057
{
2ff057
    const char *res = NULL;
2ff057
    if (rpmtdNext(td) >= 0) {
2ff057
	res = rpmtdGetString(td);
2ff057
    }
2ff057
    return res;
2ff057
}
2ff057
2ff057
char * rpmtdGetChar(rpmtd td)
2ff057
{
2ff057
    char *res = NULL;
2ff057
2ff057
    if (td != NULL && td->type == RPM_CHAR_TYPE) {
2ff057
	int ix = (td->ix >= 0 ? td->ix : 0);
2ff057
	res = (char *) td->data + ix;
2ff057
    } 
2ff057
    return res;
2ff057
}
2ff057
uint16_t * rpmtdGetUint16(rpmtd td)
2ff057
{
2ff057
    uint16_t *res = NULL;
2ff057
2ff057
    if (td != NULL && td->type == RPM_INT16_TYPE) {
2ff057
	int ix = (td->ix >= 0 ? td->ix : 0);
2ff057
	res = (uint16_t *) td->data + ix;
2ff057
    } 
2ff057
    return res;
2ff057
}
2ff057
2ff057
uint32_t * rpmtdGetUint32(rpmtd td)
2ff057
{
2ff057
    uint32_t *res = NULL;
2ff057
2ff057
    if (td != NULL && td->type == RPM_INT32_TYPE) {
2ff057
	int ix = (td->ix >= 0 ? td->ix : 0);
2ff057
	res = (uint32_t *) td->data + ix;
2ff057
    } 
2ff057
    return res;
2ff057
}
2ff057
2ff057
uint64_t * rpmtdGetUint64(rpmtd td)
2ff057
{
2ff057
    uint64_t *res = NULL;
2ff057
2ff057
    if (td != NULL && td->type == RPM_INT64_TYPE) {
2ff057
	int ix = (td->ix >= 0 ? td->ix : 0);
2ff057
	res = (uint64_t *) td->data + ix;
2ff057
    } 
2ff057
    return res;
2ff057
}
2ff057
2ff057
const char * rpmtdGetString(rpmtd td)
2ff057
{
2ff057
    const char *str = NULL;
2ff057
2ff057
    if (td == NULL)
2ff057
	return NULL;
2ff057
2ff057
    if (td->type == RPM_STRING_TYPE) {
2ff057
	str = (const char *) td->data;
2ff057
    } else if (td->type == RPM_STRING_ARRAY_TYPE ||
2ff057
	       td->type == RPM_I18NSTRING_TYPE) {
2ff057
	/* XXX TODO: check for array bounds */
2ff057
	int ix = (td->ix >= 0 ? td->ix : 0);
2ff057
	str = *((const char**) td->data + ix);
2ff057
    } 
2ff057
    return str;
2ff057
}
2ff057
2ff057
uint64_t rpmtdGetNumber(rpmtd td)
2ff057
{
2ff057
    uint64_t val = 0;
2ff057
    int ix = (td->ix >= 0 ? td->ix : 0);
2ff057
2ff057
    if (td == NULL)
2ff057
	return 0;
2ff057
2ff057
    switch (td->type) {
2ff057
    case RPM_INT64_TYPE:
2ff057
	val = *((uint64_t *) td->data + ix);
2ff057
	break;
2ff057
    case RPM_INT32_TYPE:
2ff057
	val = *((uint32_t *) td->data + ix);
2ff057
	break;
2ff057
    case RPM_INT16_TYPE:
2ff057
	val = *((uint16_t *) td->data + ix);
2ff057
	break;
2ff057
    case RPM_INT8_TYPE:
2ff057
    case RPM_CHAR_TYPE:
2ff057
	val = *((uint8_t *) td->data + ix);
2ff057
	break;
2ff057
    default:
2ff057
	break;
2ff057
    }
2ff057
    return val;
2ff057
}
2ff057
2ff057
char *rpmtdFormat(rpmtd td, rpmtdFormats fmt, const char *errmsg)
2ff057
{
2ff057
    headerFmt ext = rpmHeaderFormatByValue(fmt);
2ff057
    const char *err = NULL;
2ff057
    char *str = NULL;
2ff057
2ff057
    if (ext) {
2ff057
	str = rpmHeaderFormatCall(ext, td);
2ff057
    } else {
2ff057
	err = _("Unknown format");
2ff057
    }
2ff057
    
2ff057
    if (err && errmsg) {
2ff057
	errmsg = err;
2ff057
    }
2ff057
2ff057
    return str;
2ff057
}
2ff057
2ff057
int rpmtdSetTag(rpmtd td, rpmTagVal tag)
2ff057
{
2ff057
    rpmTagType newtype = rpmTagGetTagType(tag);
2ff057
    int rc = 0;
2ff057
2ff057
    if (td == NULL)
2ff057
	goto exit;
2ff057
2ff057
    /* 
2ff057
     * Sanity checks: 
2ff057
     * - is the new tag valid at all
2ff057
     * - if changing tag of non-empty container, require matching type 
2ff057
     */
2ff057
    if (newtype == RPM_NULL_TYPE)
2ff057
	goto exit;
2ff057
2ff057
    if (td->data || td->count > 0) {
2ff057
	if (rpmTagGetTagType(td->tag) != rpmTagGetTagType(tag)) {
2ff057
	    goto exit;
2ff057
	}
2ff057
    } 
2ff057
2ff057
    td->tag = tag;
2ff057
    td->type = newtype;
2ff057
    rc = 1;
2ff057
    
2ff057
exit:
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static inline int rpmtdSet(rpmtd td, rpmTagVal tag, rpmTagType type, 
2ff057
			    rpm_constdata_t data, rpm_count_t count)
2ff057
{
2ff057
    rpmtdReset(td);
2ff057
    td->tag = tag;
2ff057
    td->type = type;
2ff057
    td->count = count;
2ff057
    /* 
2ff057
     * Discards const, but we won't touch the data (even rpmtdFreeData()
2ff057
     * wont free it as allocation flags aren't set) so it's "ok". 
2ff057
     * XXX: Should there be a separate RPMTD_FOO flag for "user data"?
2ff057
     */
2ff057
    td->data = (void *) data;
2ff057
    return 1;
2ff057
}
2ff057
2ff057
int rpmtdFromUint8(rpmtd td, rpmTagVal tag, uint8_t *data, rpm_count_t count)
2ff057
{
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
    rpmTagReturnType retype = rpmTagGetReturnType(tag);
2ff057
    
2ff057
    if (count < 1)
2ff057
	return 0;
2ff057
2ff057
    /*
2ff057
     * BIN type is really just an uint8_t array internally, it's just
2ff057
     * treated specially otherwise.
2ff057
     */
2ff057
    switch (type) {
2ff057
    case RPM_CHAR_TYPE:
2ff057
    case RPM_INT8_TYPE:
2ff057
	if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
2ff057
	    return 0;
2ff057
	/* fallthrough */
2ff057
    case RPM_BIN_TYPE:
2ff057
	break;
2ff057
    default:
2ff057
	return 0;
2ff057
    }
2ff057
    
2ff057
    return rpmtdSet(td, tag, type, data, count);
2ff057
}
2ff057
2ff057
int rpmtdFromUint16(rpmtd td, rpmTagVal tag, uint16_t *data, rpm_count_t count)
2ff057
{
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
    rpmTagReturnType retype = rpmTagGetReturnType(tag);
2ff057
    if (type != RPM_INT16_TYPE || count < 1) 
2ff057
	return 0;
2ff057
    if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
2ff057
	return 0;
2ff057
    
2ff057
    return rpmtdSet(td, tag, type, data, count);
2ff057
}
2ff057
2ff057
int rpmtdFromUint32(rpmtd td, rpmTagVal tag, uint32_t *data, rpm_count_t count)
2ff057
{
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
    rpmTagReturnType retype = rpmTagGetReturnType(tag);
2ff057
    if (type != RPM_INT32_TYPE || count < 1) 
2ff057
	return 0;
2ff057
    if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
2ff057
	return 0;
2ff057
    
2ff057
    return rpmtdSet(td, tag, type, data, count);
2ff057
}
2ff057
2ff057
int rpmtdFromUint64(rpmtd td, rpmTagVal tag, uint64_t *data, rpm_count_t count)
2ff057
{
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
    rpmTagReturnType retype = rpmTagGetReturnType(tag);
2ff057
    if (type != RPM_INT64_TYPE || count < 1) 
2ff057
	return 0;
2ff057
    if (retype != RPM_ARRAY_RETURN_TYPE && count > 1) 
2ff057
	return 0;
2ff057
    
2ff057
    return rpmtdSet(td, tag, type, data, count);
2ff057
}
2ff057
2ff057
int rpmtdFromString(rpmtd td, rpmTagVal tag, const char *data)
2ff057
{
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
    int rc = 0;
2ff057
2ff057
    if (type == RPM_STRING_TYPE) {
2ff057
	rc = rpmtdSet(td, tag, type, data, 1);
2ff057
    } else if (type == RPM_STRING_ARRAY_TYPE) {
2ff057
	rc = rpmtdSet(td, tag, type, &data, 1);
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
int rpmtdFromStringArray(rpmtd td, rpmTagVal tag, const char **data, rpm_count_t count)
2ff057
{
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
    if (type != RPM_STRING_ARRAY_TYPE || count < 1)
2ff057
	return 0;
2ff057
    if (type == RPM_STRING_TYPE && count != 1)
2ff057
	return 0;
2ff057
2ff057
    return rpmtdSet(td, tag, type, data, count);
2ff057
}
2ff057
2ff057
int rpmtdFromArgv(rpmtd td, rpmTagVal tag, ARGV_t argv)
2ff057
{
2ff057
    int count = argvCount(argv);
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
2ff057
    if (type != RPM_STRING_ARRAY_TYPE || count < 1)
2ff057
	return 0;
2ff057
2ff057
    return rpmtdSet(td, tag, type, argv, count);
2ff057
}
2ff057
2ff057
int rpmtdFromArgi(rpmtd td, rpmTagVal tag, ARGI_t argi)
2ff057
{
2ff057
    int count = argiCount(argi);
2ff057
    rpmTagType type = rpmTagGetTagType(tag);
2ff057
    rpmTagReturnType retype = rpmTagGetReturnType(tag);
2ff057
2ff057
    if (type != RPM_INT32_TYPE || retype != RPM_ARRAY_RETURN_TYPE || count < 1)
2ff057
	return 0;
2ff057
2ff057
    return rpmtdSet(td, tag, type, argiData(argi), count);
2ff057
}
2ff057
2ff057
rpmtd rpmtdDup(rpmtd td)
2ff057
{
2ff057
    rpmtd newtd = NULL;
2ff057
    char **data = NULL;
2ff057
    int i;
2ff057
2ff057
    if (td == NULL)
2ff057
	return NULL;
2ff057
    
2ff057
    /* TODO: permit other types too */
2ff057
    if (td->type != RPM_STRING_ARRAY_TYPE && td->type != RPM_I18NSTRING_TYPE) {
2ff057
	return NULL;
2ff057
    }
2ff057
2ff057
    /* deep-copy container and data, drop immutable flag */
2ff057
    newtd = rpmtdNew();
2ff057
    memcpy(newtd, td, sizeof(*td));
2ff057
    newtd->flags &= ~(RPMTD_IMMUTABLE);
2ff057
2ff057
    newtd->flags |= (RPMTD_ALLOCED | RPMTD_PTR_ALLOCED);
2ff057
    newtd->data = data = xmalloc(td->count * sizeof(*data));
2ff057
    while ((i = rpmtdNext(td)) >= 0) {
2ff057
	data[i] = xstrdup(rpmtdGetString(td));
2ff057
    }
2ff057
2ff057
    return newtd;
2ff057
}
2ff057
2ff057
rpmsid * rpmtdToPool(rpmtd td, rpmstrPool pool)
2ff057
{
2ff057
    rpmsid *sids = NULL;
2ff057
2ff057
    if (pool && td) {
2ff057
	const char **strings = td->data;
2ff057
	switch (td->type) {
2ff057
	case RPM_STRING_ARRAY_TYPE:
2ff057
	case RPM_I18NSTRING_TYPE:
2ff057
	    sids = xmalloc(td->count * sizeof(*sids));
2ff057
	    for (rpm_count_t i = 0; i < td->count; i++)
2ff057
		sids[i] = rpmstrPoolId(pool, strings[i], 1);
2ff057
	    break;
2ff057
	}
2ff057
    }
2ff057
    return sids;
2ff057
}