240 lines
5.3 KiB
Plaintext
240 lines
5.3 KiB
Plaintext
#include "EXTERN.h"
|
|
#include "perl.h"
|
|
#include "XSUB.h"
|
|
|
|
#include "RPM.h"
|
|
|
|
static char * const rcsid = "$Id: RPM.xs,v 1.3 2000/05/30 01:03:13 rjray Exp $";
|
|
|
|
extern XS(boot_RPM__Constants);
|
|
extern XS(boot_RPM__Header);
|
|
extern XS(boot_RPM__Database);
|
|
|
|
static HV* tag2num_priv;
|
|
static HV* num2tag_priv;
|
|
static SV* errSV;
|
|
static CV* err_callback;
|
|
|
|
static void setup_tag_mappings(pTHX)
|
|
{
|
|
const char* tag;
|
|
int num;
|
|
int idx;
|
|
char str_num[8];
|
|
|
|
tag2num_priv = perl_get_hv("RPM::tag2num", TRUE);
|
|
num2tag_priv = perl_get_hv("RPM::num2tag", TRUE);
|
|
for (idx = 0; idx < rpmTagTableSize; idx++)
|
|
{
|
|
//
|
|
// For future reference: The offset of 7 used in referring to the
|
|
// (const char *) tag and its length is to discard the "RPMTAG_"
|
|
// prefix inherent in the tag names.
|
|
//
|
|
tag = rpmTagTable[idx].name;
|
|
num = rpmTagTable[idx].val;
|
|
hv_store(tag2num_priv, (char *)tag + 7, strlen(tag) - 7,
|
|
newSViv(num), FALSE);
|
|
Zero(str_num, 1, 8);
|
|
snprintf(str_num, 8, "%d", num);
|
|
hv_store(num2tag_priv, str_num, strlen(str_num),
|
|
newSVpv((char *)tag + 7, strlen(tag) - 7), FALSE);
|
|
}
|
|
}
|
|
|
|
int tag2num(pTHX_ const char* tag)
|
|
{
|
|
SV** svp;
|
|
|
|
// Get the #define value for the tag from the hash made at boot-up
|
|
svp = hv_fetch(tag2num_priv, (char *)tag, strlen(tag), FALSE);
|
|
if (! (svp && SvOK(*svp) && SvIOK(*svp)))
|
|
// Later we may need to set some sort of error message
|
|
return 0;
|
|
|
|
return (SvIV(*svp));
|
|
}
|
|
|
|
const char* num2tag(pTHX_ int num)
|
|
{
|
|
SV** svp;
|
|
char str_num[8];
|
|
SV* tmp;
|
|
|
|
Zero(str_num, 1, 8);
|
|
snprintf(str_num, 8, "%d", num);
|
|
svp = hv_fetch(num2tag_priv, str_num, strlen(str_num), FALSE);
|
|
if (! (svp && SvPOK(*svp)))
|
|
return Nullch;
|
|
|
|
return (SvPV(*svp, PL_na));
|
|
}
|
|
|
|
char* rpm_rpm_osname(void)
|
|
{
|
|
char* os_name;
|
|
int os_val;
|
|
|
|
rpmGetOsInfo((const char **)&os_name, &os_val);
|
|
return os_name;
|
|
}
|
|
|
|
char* rpm_rpm_archname(void)
|
|
{
|
|
char* arch_name;
|
|
int arch_val;
|
|
|
|
rpmGetArchInfo((const char **)&arch_name, &arch_val);
|
|
return arch_name;
|
|
}
|
|
|
|
// This is a callback routine that the bootstrapper will register with the RPM
|
|
// lib so as to catch any errors. (I hope)
|
|
static void rpm_catch_errors(pTHX)
|
|
{
|
|
int error_code;
|
|
char* error_string;
|
|
|
|
error_code = rpmErrorCode();
|
|
error_string = rpmErrorString();
|
|
|
|
// Set the string part, first
|
|
sv_setsv(errSV, newSVpv(error_string, strlen(error_string)));
|
|
// Set the IV part
|
|
sv_setiv(errSV, error_code);
|
|
// Doing that didn't erase the PV part, but it cleared the flag:
|
|
SvPOK_on(errSV);
|
|
|
|
// If there is a current callback, invoke it:
|
|
if (err_callback != NULL)
|
|
{
|
|
// This is just standard boilerplate for calling perl from C
|
|
dSP;
|
|
ENTER;
|
|
SAVETMPS;
|
|
PUSHMARK(sp);
|
|
XPUSHs(sv_2mortal(newSViv(error_code)));
|
|
XPUSHs(sv_2mortal(newSVpv(error_string, strlen(error_string))));
|
|
PUTBACK;
|
|
|
|
// The actual call
|
|
perl_call_sv((SV *)err_callback, G_DISCARD);
|
|
|
|
// More boilerplate
|
|
SPAGAIN;
|
|
PUTBACK;
|
|
FREETMPS;
|
|
LEAVE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// This is just to make available an easy way to clear both sides of $RPM::err
|
|
void clear_errors(pTHX)
|
|
{
|
|
sv_setsv(errSV, newSVpv("", 0));
|
|
sv_setiv(errSV, 0);
|
|
SvPOK_on(errSV);
|
|
|
|
return;
|
|
}
|
|
|
|
SV* set_error_callback(pTHX_ SV* newcb)
|
|
{
|
|
SV* oldcb;
|
|
|
|
oldcb = (err_callback) ? newRV((SV *)err_callback) : newSVsv(&PL_sv_undef);
|
|
|
|
if (SvROK(newcb)) newcb = SvRV(newcb);
|
|
if (SvTYPE(newcb) == SVt_PVCV)
|
|
err_callback = (CV *)newcb;
|
|
else if (SvPOK(newcb))
|
|
{
|
|
char* fn_name;
|
|
char* sv_name;
|
|
|
|
sv_name = SvPV(newcb, PL_na);
|
|
if (! strstr(sv_name, "::"))
|
|
{
|
|
Newz(TRUE, fn_name, strlen(sv_name) + 7, char);
|
|
strncat(fn_name, "main::", 6);
|
|
strcat(fn_name + 6, sv_name);
|
|
}
|
|
else
|
|
fn_name = sv_name;
|
|
|
|
err_callback = perl_get_cv(fn_name, FALSE);
|
|
}
|
|
else
|
|
{
|
|
err_callback = Null(CV *);
|
|
}
|
|
|
|
return oldcb;
|
|
}
|
|
|
|
void rpm_error(int code, const char* message)
|
|
{
|
|
rpmError(code, (char *)message);
|
|
}
|
|
|
|
|
|
MODULE = RPM PACKAGE = RPM::Error
|
|
|
|
|
|
SV*
|
|
set_error_callback(newcb)
|
|
SV* newcb;
|
|
PROTOTYPE: $
|
|
CODE:
|
|
RETVAL = set_error_callback(aTHX_ newcb);
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
void
|
|
clear_errors()
|
|
PROTOTYPE:
|
|
CODE:
|
|
clear_errors(aTHX);
|
|
|
|
void
|
|
rpm_error(code, message)
|
|
int code;
|
|
char* message;
|
|
PROTOTYPE: $$
|
|
|
|
|
|
MODULE = RPM PACKAGE = RPM PREFIX = rpm_
|
|
|
|
|
|
char*
|
|
rpm_rpm_osname()
|
|
PROTOTYPE:
|
|
|
|
char*
|
|
rpm_rpm_archname()
|
|
PROTOTYPE:
|
|
|
|
|
|
BOOT:
|
|
{
|
|
SV * config_loaded;
|
|
|
|
errSV = perl_get_sv("RPM::err", GV_ADD|GV_ADDMULTI);
|
|
config_loaded = perl_get_sv("RPM::__config_loaded", GV_ADD|GV_ADDMULTI);
|
|
if (! (SvOK(config_loaded) && SvTRUE(config_loaded)))
|
|
{
|
|
rpmReadConfigFiles(NULL, NULL);
|
|
sv_setiv(config_loaded, TRUE);
|
|
}
|
|
|
|
setup_tag_mappings();
|
|
rpmErrorSetCallback(rpm_catch_errors);
|
|
err_callback = Nullcv;
|
|
|
|
newXS("RPM::bootstrap_Constants", boot_RPM__Constants, file);
|
|
newXS("RPM::bootstrap_Header", boot_RPM__Header, file);
|
|
newXS("RPM::bootstrap_Database", boot_RPM__Database, file);
|
|
}
|