ALPM

 view release on metacpan or  search on metacpan

types.c  view on Meta::CPAN

#include <stdlib.h>
#include <string.h>
#include <alpm.h>

/* Perl API headers. */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"

#include "types.h"

/* SCALAR CONVERSIONS */

SV*
c2p_str(void *str)
{
	return newSVpv(str, 0);
}

const char*
p2c_str(SV *sv)
{
	char *pstr, *cstr;
	STRLEN len;

	/* pstr is not guaranteed to be NULL terminated so make a copy */
	pstr = SvPV(sv, len);
	cstr = calloc(len + 1, sizeof(char));
	memcpy(cstr, pstr, len);
	return cstr;
}

SV*
c2p_pkg(void *p)
{
	SV *rv = newSV(0);
	return sv_setref_pv(rv, "ALPM::Package", p);
}

ALPM_Package
p2c_pkg(SV *pkgobj)
{
	return INT2PTR(ALPM_Package, SvIV((SV*)SvRV(pkgobj)));
}

ALPM_DB
p2c_db(SV *db)
{
	return INT2PTR(ALPM_DB, SvIV((SV*)SvRV(db)));
}

SV*
c2p_localdb(void *db)
{
	SV *rv = newSV(0);
	sv_setref_pv(rv, "ALPM::DB::Local", db);
	return rv;
}

SV*
c2p_syncdb(void *db)
{
	SV *rv = newSV(0);
	sv_setref_pv(rv, "ALPM::DB::Sync", db);
	return rv;
}

SV*
c2p_db(void *db)
{
    if(strcmp(alpm_db_get_name(db), "local") == 0) {
        return c2p_localdb(db);
    } else {
        return c2p_syncdb(db);
    }
}

SV*
c2p_depmod(alpm_depmod_t mod)
{
	char *cmp;
	switch(mod){
	case 0:
	case ALPM_DEP_MOD_ANY: cmp = ""; break; /* ? */
	case ALPM_DEP_MOD_EQ: cmp = "="; break;
	case ALPM_DEP_MOD_GE: cmp = ">="; break;
	case ALPM_DEP_MOD_LE: cmp = "<="; break;
	case ALPM_DEP_MOD_GT: cmp = ">"; break;
	case ALPM_DEP_MOD_LT: cmp = "<"; break;
	default: cmp = "?";
	}

	return newSVpv(cmp, 0);
}

alpm_depmod_t
p2c_depmod(SV* mod)
{
	char *cmp = SvPV_nolen(mod);
	if(!cmp || strcmp(cmp, "") == 0) { return ALPM_DEP_MOD_ANY; }
	else if(strcmp(cmp, "=") == 0) { return ALPM_DEP_MOD_EQ; }
	else if(strcmp(cmp, ">=") == 0) { return ALPM_DEP_MOD_GE; }
	else if(strcmp(cmp, "<=") == 0) { return ALPM_DEP_MOD_LE; }
	else if(strcmp(cmp, ">") == 0) { return ALPM_DEP_MOD_GT; }
	else if(strcmp(cmp, "<") == 0) { return ALPM_DEP_MOD_LT; }
	else { return 0; /* TODO: croak */ }
}

SV*
c2p_depend(void *p)
{
	alpm_depend_t *dep;
	HV *hv;
	hv = newHV();
	dep = p;

	hv_store(hv, "name", 4, newSVpv(dep->name, 0), 0);
	hv_store(hv, "version", 7, newSVpv(dep->version, 0), 0);
	hv_store(hv, "mod", 3, c2p_depmod(dep->mod), 0);
	if(dep->desc) hv_store(hv, "desc", 4, newSVpv(dep->desc, 0), 0);
	return newRV_noinc((SV*)hv);
}

alpm_depend_t*

types.c  view on Meta::CPAN

}

SV*
c2p_conflict(void *p)
{
	alpm_conflict_t *c;
	HV *hv;
	hv = newHV();
	c = p;

	hv_store(hv, "package1", 8, newSVpv(c->package1, 0), 0);
	hv_store(hv, "package2", 8, newSVpv(c->package2, 0), 0);
	hv_store(hv, "reason", 6, c2p_depend(c->reason), 0);
	return newRV_noinc((SV*)hv);
}

static SV*
c2p_file(alpm_file_t *file){
	HV *hv;
	hv = newHV();
	hv_store(hv, "name", 4, newSVpv(file->name, 0), 0);
	hv_store(hv, "size", 4, newSViv(file->size), 0);
	hv_store(hv, "mode", 4, newSViv(file->mode), 0);
	return newRV_noinc((SV*)hv);
}

SV*
c2p_filelist(void *flistPtr){
	alpm_filelist_t *flist;
	AV *av;
	int i;

	flist = flistPtr;
	av = newAV();
	for(i = 0; i < flist->count; i++){
		av_push(av, c2p_file(flist->files + i));
	}
	return newRV_noinc((SV*)av);
}

/*
This deals with only raw bits, which is bad form, but I prefer the design.
If the alpm_siglevel_t bitflag enum was not so strange, I wouldn't have
chosen to do this.

The bit flags are separated into two halves with a special case of the
"default value" where bit 32 (the MSB) is on. Reading from LSB to MSB,
the package flags consist of the first four bits. 6 unused bits follow.
The database flags consist of the next four bits. 17 unused bits follow.
Finally, the bit flag for ALPM_USE_DEFAULT is the MSB.

Here is the form of the package and database bitmask. Remember the
database flags are shifted to the left by 10 places.

BIT	DESCRIPTION
1	Signature checking is enabled for packages or databases respectively.
2	Signature checking is optional, used only when available.
3	MARGINAL_OK?
4	UNKNOWN_OK?

A setting of TrustAll in pacman.conf enables MARGINAL_OK and UNKNOWN_OK.
These two flags are not enabled separately from one another.

ALPM_SIG_USE_DEFAULT is the default value when set_default_siglevel is never
called but I have no idea what that could mean when this is the value of the default.
This seems to be a circular argument with no end.

*/

#define MASK_ENABLE 1
#define MASK_OPT 3
#define MASK_TRUSTALL 12
#define MASK_ALL 15
#define OFFSET_DB 10

static
SV* truststring(unsigned long siglvl)
{
	SV *str;
	if(!(siglvl & MASK_ENABLE)){
		return newSVpv("never", 0);
	}else if(!(~siglvl & MASK_OPT)){
		str = newSVpv("optional", 0);
	}else{
		str = newSVpv("required", 0);
	}
	if(!(~siglvl & MASK_TRUSTALL)){
		sv_catpv(str, " trustall");
	}
	return str;
}

/* converts siglevel bitflags into a string (default/never) or hashref of strings */
SV*
c2p_siglevel(alpm_siglevel_t sig)
{
	HV *hv;

	if(sig & ALPM_SIG_USE_DEFAULT){
		return newSVpv("default", 7);
	}

	hv = newHV();
	hv_store(hv, "pkg", 3, truststring(sig & MASK_ALL), 0);
	hv_store(hv, "db", 2, truststring((sig >> OFFSET_DB) & MASK_ALL), 0);
	return newRV_noinc((SV*)hv);
}

static unsigned long
trustmask(char *str, STRLEN len)
{
	unsigned long flags;

	if(len == 5 && strncmp(str, "never", 5) == 0){
		return 0;
	}

	if(len < 8){
		goto badstr;
	}else if(strncmp(str, "required", 8) == 0){
		flags = MASK_ENABLE;
	}else if(strncmp(str, "optional", 8) == 0){
		flags = MASK_OPT;
	}else {



( run in 1.123 second using v1.01-cache-2.11-cpan-39bf76dae61 )