summaryrefslogtreecommitdiffstats
path: root/RPM4/src
diff options
context:
space:
mode:
authornanardon <nanardon@971eb68f-4bfb-0310-8326-d2484c010a4c>2005-10-04 04:08:46 +0000
committernanardon <nanardon@971eb68f-4bfb-0310-8326-d2484c010a4c>2005-10-04 04:08:46 +0000
commit9e2966a33f9148fdc8ef81783bab1fe18e87bd34 (patch)
tree7497629483bdfca79e64991306f251dfdc9bdafb /RPM4/src
parent588601a22c421404c9db24e0a47330d2186977f9 (diff)
downloadperl-RPM4-9e2966a33f9148fdc8ef81783bab1fe18e87bd34.tar
perl-RPM4-9e2966a33f9148fdc8ef81783bab1fe18e87bd34.tar.gz
perl-RPM4-9e2966a33f9148fdc8ef81783bab1fe18e87bd34.tar.bz2
perl-RPM4-9e2966a33f9148fdc8ef81783bab1fe18e87bd34.tar.xz
perl-RPM4-9e2966a33f9148fdc8ef81783bab1fe18e87bd34.zip
- move to trunk
git-svn-id: svn+ssh://haiku.zarb.org/home/projects/rpm4/svn/trunk@36 971eb68f-4bfb-0310-8326-d2484c010a4c
Diffstat (limited to 'RPM4/src')
-rw-r--r--RPM4/src/Makefile.PL48
-rw-r--r--RPM4/src/RPM4.h119
-rw-r--r--RPM4/src/RPM4.xs2832
-rw-r--r--RPM4/src/RPM4sign.c28
-rw-r--r--RPM4/src/typemap21
5 files changed, 3048 insertions, 0 deletions
diff --git a/RPM4/src/Makefile.PL b/RPM4/src/Makefile.PL
new file mode 100644
index 0000000..9b9a60f
--- /dev/null
+++ b/RPM4/src/Makefile.PL
@@ -0,0 +1,48 @@
+# $Id$
+
+# use 5.008;
+use ExtUtils::MakeMaker;
+
+my ($obj, $ldd, $fl) =
+ -f '/usr/include/rpmconstant/rpmconstant.h' ?
+ ('', '-lrpmconstant', '-DHAVE_RPMCONSTANT') :
+ ('rpmconstant.o rpmconstant_internal.o rpmconstanttbl.o', '', '');
+
+sub MY::postamble {
+ my $first = <<RPMCONSTTBL;
+
+rpmconstanttbl.c: Makefile rpmh2tbl
+ perl rpmh2tbl /usr/include/rpm/*.h > \$@
+RPMCONSTTBL
+ # This code is to reduce duplication of files
+ # in fact it is only usefull for the maintainers of this module
+ # if you get the module from CPAN, those files are allready here
+ # if you're building from svn, you need rpmconstant directory
+ my $second = "";
+ if(-d '../../rpmconstant') {
+ $second = <<RPMCONST
+rpmconstant.c: ../../rpmconstant/rpmconstant.c
+ cp -a \$< \$@
+
+rpmconstant.h: ../../rpmconstant/rpmconstant.h
+ cp -a \$< \$@
+
+rpmconstant_internal.c: ../../rpmconstant/rpmconstant_internal.c
+ cp -a \$< \$@
+
+rpmh2tbl: ../../rpmconstant/rpmh2tbl
+ cp -a \$< \$@
+RPMCONST
+ }
+
+ $first . $second
+}
+
+WriteMakefile(
+ NAME => 'RPM4',
+ VERSION_FROM => '../lib/RPM4.pm',
+ OBJECT => "RPM4.o RPM4sign.o $obj",
+ INC => '-I/usr/include/rpm',
+ LIBS => "-lrpm -lrpmio -lrpmdb -lrpmbuild -lpopt -lz -lbz2 $ldd",
+ 'CCFLAGS' => $fl,
+);
diff --git a/RPM4/src/RPM4.h b/RPM4/src/RPM4.h
new file mode 100644
index 0000000..fcad6b0
--- /dev/null
+++ b/RPM4/src/RPM4.h
@@ -0,0 +1,119 @@
+/* $Id$ */
+
+#ifndef _HDLIST_H
+#define _HDLIST_H
+
+#include "header.h"
+
+/* Hdlistsign.c: imported but modified functions */
+
+int rpmsign(char *passphrase, const char *rpm);
+
+int rpmchecksig(rpmts ts, const char * filename, int flags);
+
+/* rpmlib does not export some usefull functions
+ * We Import its here
+ * This File should be the last included */
+
+/* From rpmlead.h */
+
+#ifndef _H_RPMLEAD
+
+rpmRC writeLead(FD_t fd, const struct rpmlead *lead);
+rpmRC readLead(FD_t fd, struct rpmlead *lead);
+
+#endif /* _H_RPMLEAD */
+
+/* From signature.h */
+
+#ifndef H_SIGNATURE
+
+typedef enum sigType_e {
+ RPMSIGTYPE_HEADERSIG= 5
+} sigType;
+
+typedef enum pgpVersion_e {
+ PGP_NOTDETECTED = -1,
+ PGP_UNKNOWN = 0,
+ PGP_2 = 2,
+ PGP_5 = 5
+} pgpVersion;
+
+Header rpmNewSignature(void);
+
+rpmRC rpmReadSignature(FD_t fd, Header *sighp,
+ sigType sig_type, const char ** msg);
+
+int rpmWriteSignature(FD_t fd, Header h);
+
+int rpmAddSignature(Header sig, const char * file,
+ int_32 sigTag, const char * passPhrase);
+
+#define RPMLOOKUPSIG_QUERY 0 /*!< Lookup type in effect */
+#define RPMLOOKUPSIG_DISABLE 1 /*!< Disable (--sign was not given) */
+#define RPMLOOKUPSIG_ENABLE 2 /*!< Re-enable %_signature */
+
+int rpmLookupSignatureType(int action);
+
+char * rpmGetPassPhrase(const char * prompt,
+ const int sigTag);
+
+const char * rpmDetectPGPVersion(pgpVersion * pgpVer);
+
+#endif /* H_SIGNATURE */
+
+#ifndef H_HEADER_INTERNAL
+
+#ifdef HD_HEADER_INTERNAL
+/** \ingroup header
+ * Description of tag data.
+ */
+typedef /*@abstract@*/ struct entryInfo_s * entryInfo;
+struct entryInfo_s {
+ int_32 tag; /*!< Tag identifier. */
+ int_32 type; /*!< Tag data type. */
+ int_32 offset; /*!< Offset into data segment (ondisk only). */
+ int_32 count; /*!< Number of tag elements. */
+};
+
+/** \ingroup header
+ * A single tag from a Header.
+ */
+typedef /*@abstract@*/ struct indexEntry_s * indexEntry;
+struct indexEntry_s {
+ struct entryInfo_s info; /*!< Description of tag data. */
+/*@owned@*/
+ void * data; /*!< Location of tag data. */
+ int length; /*!< No. bytes of data. */
+ int rdlen; /*!< No. bytes of data in region. */
+};
+
+struct headerToken_s {
+ /*@unused@*/
+ struct HV_s hv; /*!< Header public methods. */
+ /*@only@*/ /*@null@*/
+ void * blob; /*!< Header region blob. */
+ /*@owned@*/
+ indexEntry index; /*!< Array of tags. */
+ int indexUsed; /*!< Current size of tag array. */
+ int indexAlloced; /*!< Allocated size of tag array. */
+ int flags;
+#define HEADERFLAG_SORTED (1 << 0) /*!< Are header entries sorted? */
+#define HEADERFLAG_ALLOCATED (1 << 1) /*!< Is 1st header region allocated? */
+#define HEADERFLAG_LEGACY (1 << 2) /*!< Header came from legacy source? */
+#define HEADERFLAG_DEBUG (1 << 3) /*!< Debug this header? */
+ /*@refs@*/
+ int nrefs; /*!< Reference count. */
+};
+#endif
+
+#endif /* H_HEADER_INTERNAL */
+
+#ifndef H_LEGACY
+
+void compressFilelist(Header h);
+void expandFilelist(Header h);
+
+#endif /* H_LEGACY */
+
+#endif
diff --git a/RPM4/src/RPM4.xs b/RPM4/src/RPM4.xs
new file mode 100644
index 0000000..77198e7
--- /dev/null
+++ b/RPM4/src/RPM4.xs
@@ -0,0 +1,2832 @@
+/* Nanar <nanardon@mandrake.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* $Id$ */
+
+/* PREPROSSEUR FLAGS
+ * HHACK: if defined, activate some functions or behaviour for expert user who
+ * want hacking purpose in their perl code
+ * HDLISTDEBUG: activate some debug code
+ * HDRPMDEBUG: activate rpm debug internals flags
+ * HDRPMMEM: print message about Free()/New on rpm
+ * HDEBUG: active all debug flags
+ */
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#undef Fflush
+#undef Mkdir
+#undef Stat
+
+/* copy data into rpm or use the header */
+#define O_SCAREMEM 1 /* If returning perl object */
+#define SCAREMEM 1
+
+/* Pre processor flags for debugging purpose */
+
+#ifdef HDEBUG
+ #undef HDLISTDEBUG
+ #define HDLISTDEBUG
+ #undef HDRPMDEBUG
+ #define HDRPMDEBUG
+ #undef HDRPMMEM
+ #define HDRPMMEM
+#endif
+
+#ifdef HDRPMMEM
+ #define PRINTF_FREE(o, a, r) fprintf(stderr, "HDEBUG FREE: %s[%p], %d at %s:%d\n", (o), (a), (r), CopFILE(PL_curcop), CopLINE(PL_curcop))
+ #define PRINTF_NEW(o, a, r) fprintf(stderr, "HDEBUG NEW : %s[%p], %d at %s:%d\n", (o), (a), (r), CopFILE(PL_curcop), CopLINE(PL_curcop))
+#endif
+
+#ifdef HDLISTDEBUG
+ #define PRINTF_CALL fprintf(stderr, "HDEBUG RUN: %s() at %s:%d\n", __FUNCTION__, CopFILE(PL_curcop), CopLINE(PL_curcop))
+#endif
+
+#if defined(HDRPMMEM) || defined(HDRPMDEBUG)
+ #define _RPMDS_INTERNAL
+ #define _RPMFI_INTERNAL
+ #define _RPMTS_INTERNAL
+ #define HD_HEADER_INTERNAL
+#endif
+
+#include <rpm/header.h>
+#include <rpm/rpmio.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmte.h>
+#include <rpm/rpmps.h>
+#include <rpm/rpmds.h>
+#include <rpm/rpmfi.h>
+#include <rpm/rpmpgp.h>
+#include <rpm/misc.h>
+#include <rpm/rpmbuild.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmpgp.h>
+
+#ifdef HAVE_RPMCONSTANT
+#include <rpmconstant/rpmconstant.h>
+#else
+#include "rpmconstant.h"
+#endif
+
+#include "RPM4.h"
+
+static unsigned char header_magic[8] = {
+ 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
+};
+
+#define CHECK_RPMDS_IX(dep) if (rpmdsIx((dep)) < 0) croak("You call RPM4::Header::Dependencies method after lastest next() of before init()")
+
+#define bless_rpmds "RPM4::Header::Dependencies"
+#define bless_rpmps "RPM4::Db::_Problems"
+#define bless_rpmts "RPM4::Transaction"
+#define bless_header "RPM4::Header"
+#define bless_rpmfi "RPM4::Header::Files"
+#define bless_spec "RPM4::Spec"
+
+/* The perl callback for output err messages */
+SV * log_callback_function = NULL;
+
+static int scalar2constant(SV * svconstant, const char * context, int * val) {
+ int rc = 0;
+ if (!svconstant || !SvOK(svconstant)) {
+ warn("Use of an undefined value");
+ return 0;
+ } else if (SvIOK(svconstant)) {
+ *val = SvIV(svconstant);
+ rc = 1;
+ } else if (SvPOK(svconstant)) {
+ rc = rpmconstantFindName((char *)context, (void *) SvPV_nolen(svconstant), val, 0);
+ } else {
+ }
+ return rc;
+}
+
+static int sv2constant(SV * svconstant, const char * context) {
+ AV * avparam;
+ int val = 0;
+ SV **tmpsv;
+ int i;
+ if (svconstant == NULL) {
+ return 0;
+ } else if (!SvOK(svconstant)) {
+ return 0;
+ } else if (SvPOK(svconstant) || SvIOK(svconstant)) {
+ if (!scalar2constant(svconstant, context, &val))
+ warn("Unknow value '%s' in '%s'", SvPV_nolen(svconstant), context);
+ } else if (SvTYPE(SvRV(svconstant)) == SVt_PVAV) {
+ avparam = (AV*) SvRV(svconstant);
+ for (i = 0; i <= av_len(avparam); i++) {
+ tmpsv = av_fetch(avparam, i, 0);
+ if (!scalar2constant(*tmpsv, context, &val))
+ warn("Unknow value '%s' in '%s' from array", SvPV_nolen(*tmpsv), context);
+ }
+ } else {
+ }
+ return val;
+}
+
+/* Parse SV arg and return assossiated RPMLOG value */
+#define sv2loglevel(sv) sv2constant((sv), "rpmlog")
+
+#define sv2deptag(sv) sv2constant((sv), "rpmtag")
+
+/* compatibility */
+#define sv2sens(sv) sv2senseflags(sv)
+
+#define sv2vsflags(sv) sv2constant((sv), "rpmvsflags")
+
+#define sv2transflags(sv) sv2constant((sv), "rpmtransflags")
+
+static rpmTag sv2dbquerytag(SV * sv_tag) {
+ int val = 0;
+ if (!scalar2constant(sv_tag, "rpmdbi", &val) && !scalar2constant(sv_tag, "rpmtag", &val))
+ croak("unknown tag value '%s'", SvPV_nolen(sv_tag));
+ return val;
+}
+
+#define sv2rpmbuildflags(sv) sv2constant((sv), "rpmbuildflags")
+
+#define sv2fileattr(sv) sv2constant((sv), "rpmfileattrs")
+
+#define sv2senseflags(sv) sv2constant((sv), "rpmsenseflags")
+
+#define sv2tagtype(sv) sv2constant((sv), "rpmtagtype")
+
+/* This function replace the standard rpmShowProgress callback
+ * during transaction to allow perl callback */
+
+void * transCallback(const void *h,
+ const rpmCallbackType what,
+ const unsigned long amount,
+ const unsigned long total,
+ const void * pkgKey,
+ void * data) {
+
+ /* The call back is used to open/close file, so we fix value, run the perl callback
+ * and let rpmShowProgress from rpm rpmlib doing its job.
+ * This unsure we'll not have to follow rpm code at each change. */
+ const char * filename = (const char *)pkgKey;
+ const char * s_what = NULL;
+ dSP;
+
+#ifdef HDLISTDEBUG
+ fprintf(stderr, "HDEBUG: RPM4: running Callback transCallback()");
+#endif
+
+ PUSHMARK(SP);
+
+ switch (what) {
+ case RPMCALLBACK_UNKNOWN:
+ s_what = "UNKNOWN";
+ break;
+ case RPMCALLBACK_INST_OPEN_FILE:
+ if (filename != NULL && filename[0] != '\0') {
+ XPUSHs(sv_2mortal(newSVpv("filename", 0)));
+ XPUSHs(sv_2mortal(newSVpv(filename, 0)));
+ }
+ s_what = "INST_OPEN_FILE";
+ break;
+ case RPMCALLBACK_INST_CLOSE_FILE:
+ s_what = "INST_CLOSE_FILE";
+ break;
+ case RPMCALLBACK_INST_PROGRESS:
+ s_what = "INST_PROGRESS";
+ break;
+ case RPMCALLBACK_INST_START:
+ s_what = "INST_START";
+ if (h) {
+ XPUSHs(sv_2mortal(newSVpv("header", 0)));
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, &h)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, &h, -1);
+#endif
+ }
+ break;
+ case RPMCALLBACK_TRANS_PROGRESS:
+ s_what = "TRANS_PROGRESS";
+ break;
+ case RPMCALLBACK_TRANS_START:
+ s_what = "TRANS_START";
+ break;
+ case RPMCALLBACK_TRANS_STOP:
+ s_what = "TRANS_STOP";
+ break;
+ case RPMCALLBACK_UNINST_PROGRESS:
+ s_what = "UNINST_PROGRESS";
+ break;
+ case RPMCALLBACK_UNINST_START:
+ s_what = "UNINST_START";
+ break;
+ case RPMCALLBACK_UNINST_STOP:
+ s_what = "UNINST_STOP";
+ break;
+ case RPMCALLBACK_REPACKAGE_PROGRESS:
+ s_what = "REPACKAGE_PROGRESS";
+ break;
+ case RPMCALLBACK_REPACKAGE_START:
+ s_what = "REPACKAGE_START";
+ break;
+ case RPMCALLBACK_REPACKAGE_STOP:
+ s_what = "REPACKAGE_STOP";
+ break;
+ case RPMCALLBACK_UNPACK_ERROR:
+ s_what = "UNPACKAGE_ERROR";
+ break;
+ case RPMCALLBACK_CPIO_ERROR:
+ s_what = "CPIO_ERROR";
+ break;
+ }
+
+ XPUSHs(sv_2mortal(newSVpv("what", 0)));
+ XPUSHs(sv_2mortal(newSVpv(s_what, 0)));
+ XPUSHs(sv_2mortal(newSVpv("amount", 0)));
+ XPUSHs(sv_2mortal(newSViv(amount)));
+ XPUSHs(sv_2mortal(newSVpv("total", 0)));
+ XPUSHs(sv_2mortal(newSViv(total)));
+ PUTBACK;
+ call_sv((SV *) data, G_DISCARD | G_SCALAR);
+ SPAGAIN;
+
+ /* Running rpmlib callback, returning its value */
+ return rpmShowProgress(h,
+ what,
+ amount,
+ total,
+ pkgKey,
+ (long *) INSTALL_NONE /* shut up */);
+}
+
+/* This function is called by rpm if a callback
+ * is set for for the logging system.
+ * If the callback is set, rpm does not print any message,
+ * and let the callback to do it */
+void logcallback(void) {
+ dSP;
+ if (log_callback_function) {
+ int logcode = rpmlogCode();
+#ifdef HDLISTDEBUG
+ fprintf(stderr, "HDEBUG: RPM4: running Callback logcallback()");
+#endif
+
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(newSVpv("logcode", 0)));
+ XPUSHs(sv_2mortal(newSViv(logcode)));
+ XPUSHs(sv_2mortal(newSVpv("msg", 0)));
+ XPUSHs(sv_2mortal(newSVpv(rpmlogMessage(), 0)));
+ XPUSHs(sv_2mortal(newSVpv("priority", 0)));
+ XPUSHs(sv_2mortal(newSViv(RPMLOG_PRI(logcode))));
+ PUTBACK;
+ call_sv(log_callback_function, G_DISCARD | G_SCALAR);
+ SPAGAIN;
+ }
+}
+
+/* This callback is run during transcheck */
+int transSolveCallback(rpmts ts, rpmds Dep, const void * data) {
+ int rc = 0;
+ int count;
+ dSP;
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ /* Should return -1 retry, 0 ignore, 1 not found */
+ rc = rpmtsSolve(ts, Dep, data);
+ /* PUSHMARK(SP); */
+ if (ts) {
+ XPUSHs(sv_2mortal(newSVpv("db", 0)));
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmts, rpmtsLink(ts, "RPM4 transSolveCallback()"))));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmts, ts, ts->nrefs);
+#endif
+
+ }
+ if (Dep) {
+ XPUSHs(sv_2mortal(newSVpv("dep", 0)));
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, rpmdsLink(Dep, "RPM4 transSolveCallback()"))));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmds, Dep, Dep->nrefs);
+#endif
+ }
+ XPUSHs(sv_2mortal(newSVpv("rc", 0)));
+ XPUSHs(sv_2mortal(newSViv(rc)));
+ PUTBACK;
+ count = call_sv((SV *) data, G_SCALAR);
+ SPAGAIN;
+ if (count) {
+ rc = POPi;
+ if (rc < -1 || rc > 1)
+ croak("Uh Oh! Your perl callback should return 1 (retry), 0 (ignore) or 1 (not found) and not %d", rc);
+ } else {
+ rc = 1;
+ }
+ return rc;
+}
+
+/**************************************************
+ * Real Function rpmts function with double call *
+ * Aka function(arg) or RPM4::Db->function(arg) *
+ * This permit to reuse existing rpmts object *
+ **************************************************/
+
+void _rpm2header(rpmts ts, char * filename, int checkmode) {
+ FD_t fd;
+ Header ret = NULL;
+ rpmRC rc;
+ dSP;
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ if ((fd = Fopen(filename, "r"))) {
+ rc = rpmReadPackageFile(ts, fd, filename, &ret);
+ if (checkmode) {
+ XPUSHs(sv_2mortal(newSViv(rc)));
+ ret = headerFree(ret); /* For checking the package, we don't keep the header */
+ } else {
+ if (rc == 0) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)ret)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, ret, ret->nrefs);
+#endif
+ } else {
+ XPUSHs(sv_2mortal(&PL_sv_undef));
+ }
+ }
+ Fclose(fd);
+ } else {
+ XPUSHs(sv_2mortal(&PL_sv_undef));
+ }
+
+ PUTBACK;
+ return;
+}
+
+void _newdep(SV * sv_deptag, char * name, SV * sv_sense, SV * sv_evr) {
+ rpmTag deptag = 0;
+ rpmsenseFlags sense = RPMSENSE_ANY;
+ rpmds Dep;
+ char * evr = NULL;
+ dSP;
+
+ if (sv_deptag && SvOK(sv_deptag))
+ deptag = sv2deptag(sv_deptag);
+ if (sv_sense && SvOK(sv_sense))
+ sense = sv2sens(sv_sense);
+ if (sv_evr && SvOK(sv_evr))
+ evr = SvPV_nolen(sv_evr);
+ Dep = rpmdsSingle(deptag,
+ name,
+ evr ? evr : "", sense);
+ if (Dep) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, Dep)));
+ }
+ PUTBACK;
+}
+
+/* Get a new specfile */
+void _newspec(rpmts ts, char * filename, SV * svpassphrase, SV * svrootdir, SV * svcookies, SV * svanyarch, SV * svforce) {
+ Spec spec = NULL;
+ char * passphrase = NULL;
+ char * rootdir = NULL;
+ char * cookies = NULL;
+ int anyarch = 0;
+ int force = 0;
+
+ if (svpassphrase && SvOK(svpassphrase))
+ passphrase = SvPV_nolen(svpassphrase);
+
+ if (svrootdir && SvOK(svrootdir))
+ rootdir = SvPV_nolen(svrootdir);
+ else
+ rootdir = "/";
+
+ if (svcookies && SvOK(svcookies))
+ cookies = SvPV_nolen(svcookies);
+
+ if (svanyarch && SvOK(svanyarch))
+ anyarch = SvIV(svanyarch);
+
+ if (svforce && SvOK(svforce))
+ force = SvIV(svforce);
+
+ dSP;
+ if (filename) {
+ if (!parseSpec(ts, filename, rootdir, NULL, 0, passphrase, cookies, anyarch, force))
+ spec = rpmtsSetSpec(ts, NULL);
+#ifdef HHACK
+ } else {
+ spec = newSpec();
+#endif
+ }
+ if (spec) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_spec, (void *)spec)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_spec, spec, -1);
+#endif
+ } else
+ XPUSHs(sv_2mortal(&PL_sv_undef));
+ PUTBACK;
+ return;
+}
+
+/* Building a spec file */
+int _specbuild(rpmts ts, Spec spec, SV * sv_buildflags) {
+ rpmBuildFlags buildflags = sv2rpmbuildflags(sv_buildflags);
+ if (buildflags == RPMBUILD_NONE) croak("No action given for build");
+ return buildSpec(ts, spec, buildflags, 0);
+}
+
+void _installsrpms(rpmts ts, char * filename) {
+ const char * specfile = NULL;
+ const char * cookies = NULL;
+ dSP;
+ if (rpmInstallSource(
+ ts,
+ filename,
+ &specfile,
+ &cookies) == 0) {
+ XPUSHs(sv_2mortal(newSVpv(specfile, 0)));
+ XPUSHs(sv_2mortal(newSVpv(cookies, 0)));
+ }
+ PUTBACK;
+}
+
+int _header_vs_dep(Header h, rpmds dep, int nopromote) {
+ CHECK_RPMDS_IX(dep);
+ return rpmdsAnyMatchesDep(h, dep, nopromote);
+ /* return 1 if match */
+}
+
+int _headername_vs_dep(Header h, rpmds dep, int nopromote) {
+ char *name; int type;
+ int rc = 0;
+ CHECK_RPMDS_IX(dep);
+ headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, NULL);
+ if (strcmp(name, rpmdsN(dep)) != 0)
+ rc = 0;
+ else
+ rc = rpmdsNVRMatchesDep(h, dep, nopromote);
+ headerFreeData(name, type);
+ return rc;
+ /* return 1 if match */
+}
+
+MODULE = RPM4 PACKAGE = RPM4
+
+BOOT:
+if (rpmReadConfigFiles(NULL, NULL) != 0)
+ croak("Can't read configuration");
+#ifdef HDLISTDEBUG
+rpmSetVerbosity(RPMMESS_DEBUG);
+#else
+rpmSetVerbosity(RPMMESS_NORMAL);
+#endif
+#ifdef HDRPMDEBUG
+_rpmds_debug = -1;
+_rpmdb_debug = -1;
+_rpmts_debug = -1;
+_rpmfi_debug = -1;
+_rpmte_debug = -1;
+#endif
+
+int
+isdebug()
+ CODE:
+#ifdef HDLISTDEBUG
+ RETVAL = 1;
+#else
+ RETVAL = 0;
+#endif
+ OUTPUT:
+ RETVAL
+
+void
+moduleinfo()
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv("Hack", 0)));
+#ifdef HHACK
+ XPUSHs(sv_2mortal(newSVpv("Yes", 0)));
+#else
+ XPUSHs(sv_2mortal(newSVpv("No", 0)));
+#endif
+ XPUSHs(sv_2mortal(newSVpv("RPMVERSION", 0)));
+ XPUSHs(sv_2mortal(newSVpv("RPMVERSION", 0)));
+ XPUSHs(sv_2mortal(newSVpv(RPMVERSION, 0)));
+ XPUSHs(sv_2mortal(newSVpv("RPM4VERSION", 0)));
+ XPUSHs(sv_2mortal(newSVpv(VERSION, 0)));
+ XPUSHs(sv_2mortal(newSVpv("RPMNAME", 0)));
+ XPUSHs(sv_2mortal(newSVpv(rpmNAME, 0)));
+ XPUSHs(sv_2mortal(newSVpv("RPMEVR", 0)));
+ XPUSHs(sv_2mortal(newSVpv(rpmEVR, 0)));
+
+# Functions to control log/verbosity
+
+void
+setverbosity(svlevel)
+ SV * svlevel
+ CODE:
+ rpmSetVerbosity(sv2loglevel(svlevel));
+
+void
+setlogcallback(function)
+ SV * function
+ CODE:
+ if (function == NULL || !SvOK(function)) {
+ rpmlogSetCallback(NULL);
+ } else if (SvTYPE(SvRV(function)) == SVt_PVCV) {
+ log_callback_function = newSVsv(function);
+ rpmlogSetCallback(logcallback);
+ } else
+ croak("First arg is not a code reference");
+
+void
+lastlogmsg()
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmlogCode())));
+ XPUSHs(sv_2mortal(newSVpv(rpmlogMessage(), 0)));
+
+int
+setlogfile(filename)
+ char * filename
+ PREINIT:
+ FILE * ofp = NULL;
+ FILE * fp = NULL;
+ CODE:
+ if (filename && *filename != 0) {
+ if ((fp = fopen(filename, "a+")) == NULL) {
+ XSprePUSH; PUSHi((IV)0);
+ XSRETURN(1);
+ }
+ }
+ if((ofp = rpmlogSetFile(fp)) != NULL)
+ fclose(ofp);
+ RETVAL=1;
+ OUTPUT:
+ RETVAL
+
+int
+readconfig(rcfile = NULL, target = NULL)
+ char * rcfile
+ char * target
+ CODE:
+ RETVAL = rpmReadConfigFiles(rcfile, target);
+ OUTPUT:
+ RETVAL
+
+void
+rpmlog(svcode, msg)
+ SV * svcode
+ char * msg
+ CODE:
+ rpmlog(sv2loglevel(svcode), "%s", msg);
+
+# Return hash of know tag
+# Name => internal key (if available)
+
+void
+querytag()
+ PREINIT:
+ int i = 0;
+ const struct headerSprintfExtension_s * ext = rpmHeaderFormats;
+ PPCODE:
+ for (i = 0; i < rpmTagTableSize; i++) {
+ XPUSHs(sv_2mortal(newSVpv(rpmTagTable[i].name + 7, 0)));
+ XPUSHs(sv_2mortal(newSViv(rpmTagTable[i].val)));
+ }
+
+ while (ext->name != NULL) {
+ if (ext->type == HEADER_EXT_MORE) {
+ ext = ext->u.more;
+ continue;
+ }
+ for (i = 0; i < rpmTagTableSize; i++) {
+ if (!strcmp(rpmTagTable[i].name, ext->name))
+ break;
+ }
+ if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG) {
+ XPUSHs(sv_2mortal(newSVpv(ext->name + 7, 0)));
+ XPUSHs(sv_newmortal());
+ }
+ ext++;
+ }
+
+int
+tagtypevalue(svtagtype)
+ SV * svtagtype
+ CODE:
+ RETVAL = sv2tagtype(svtagtype);
+ OUTPUT:
+ RETVAL
+
+int
+tagValue(tagname)
+ char * tagname
+ CODE:
+ RETVAL = tagValue((const char *) tagname);
+ OUTPUT:
+ RETVAL
+
+void
+tagName(tag)
+ int tag
+ PREINIT:
+ const char *r = NULL;
+ PPCODE:
+ r = tagName(tag);
+ XPUSHs(sv_2mortal(newSVpv(r, 0)));
+
+void
+flagvalue(flagtype, sv_value)
+ char * flagtype
+ SV * sv_value
+ PPCODE:
+ if (strcmp(flagtype, "loglevel") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2constant(sv_value, "rpmlog"))));
+ } else if (strcmp(flagtype, "deptag") == 0) { /* Who will use this ?? */
+ XPUSHs(sv_2mortal(newSViv(sv2deptag(sv_value))));
+ } else if (strcmp(flagtype, "vsf") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2constant(sv_value, "rpmverifyflags"))));
+ } else if (strcmp(flagtype, "trans") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2transflags(sv_value))));
+ } else if (strcmp(flagtype, "dbquery") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2dbquerytag(sv_value))));
+ } else if (strcmp(flagtype, "build") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2rpmbuildflags(sv_value))));
+ } else if (strcmp(flagtype, "fileattr") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2fileattr(sv_value))));
+ } else if (strcmp(flagtype, "sense") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2senseflags(sv_value))));
+ } else if (strcmp(flagtype, "tagtype") == 0) {
+ XPUSHs(sv_2mortal(newSViv(sv2tagtype(sv_value))));
+ } else if (strcmp(flagtype, "list") == 0) {
+ XPUSHs(sv_2mortal(newSVpv("loglevel", 0)));
+ XPUSHs(sv_2mortal(newSVpv("deptag", 0)));
+ XPUSHs(sv_2mortal(newSVpv("vsf", 0)));
+ XPUSHs(sv_2mortal(newSVpv("trans", 0)));
+ XPUSHs(sv_2mortal(newSVpv("dbquery", 0)));
+ XPUSHs(sv_2mortal(newSVpv("build", 0)));
+ XPUSHs(sv_2mortal(newSVpv("fileattr", 0)));
+ XPUSHs(sv_2mortal(newSVpv("tagtype", 0)));
+ }
+
+# Macros functions:
+
+void
+expand(name)
+ char * name
+ PPCODE:
+ const char * value = rpmExpand(name, NULL);
+ XPUSHs(sv_2mortal(newSVpv(value, 0)));
+
+void
+expandnumeric(name)
+ char *name
+ PPCODE:
+ int value = rpmExpandNumeric(name);
+ XPUSHs(sv_2mortal(newSViv(value)));
+
+void
+add_macro(macro)
+ char * macro
+ CODE:
+ rpmDefineMacro(NULL, macro, RMIL_DEFAULT);
+
+void
+del_macro(name)
+ char * name
+ CODE:
+ delMacro(NULL, name);
+
+void
+loadmacrosfile(filename)
+ char * filename
+ PPCODE:
+ rpmInitMacros(NULL, filename);
+
+void
+resetmacros()
+ PPCODE:
+ rpmFreeMacros(NULL);
+
+void
+resetrc()
+ PPCODE:
+ rpmFreeRpmrc();
+
+void
+getosname()
+ PREINIT:
+ const char *v = NULL;
+ PPCODE:
+ rpmGetOsInfo(&v, NULL);
+ XPUSHs(sv_2mortal(newSVpv(v, 0)));
+
+void
+getarchname()
+ PREINIT:
+ const char *v = NULL;
+ PPCODE:
+ rpmGetArchInfo(&v, NULL);
+ XPUSHs(sv_2mortal(newSVpv(v, 0)));
+
+int
+osscore(os, build = 0)
+ char * os
+ int build;
+ PREINIT:
+ int machtable;
+ CODE:
+ machtable = build ? RPM_MACHTABLE_BUILDOS : RPM_MACHTABLE_INSTOS;
+ RETVAL = rpmMachineScore(machtable, os);
+ OUTPUT:
+ RETVAL
+
+int
+archscore(arch, build = 0)
+ char * arch
+ int build;
+ PREINIT:
+ int machtable;
+ CODE:
+ machtable = build ? RPM_MACHTABLE_BUILDARCH : RPM_MACHTABLE_INSTARCH;
+ RETVAL = rpmMachineScore(machtable, arch);
+ OUTPUT:
+ RETVAL
+
+void
+buildhost()
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(buildHost(),0)));
+
+# Dump to file functions:
+void
+dumprc(fp)
+ FILE *fp
+ CODE:
+ rpmShowRC(fp);
+
+void
+dumpmacros(fp)
+ FILE *fp
+ CODE:
+ rpmDumpMacroTable(NULL, fp);
+
+int
+rpmvercmp(one, two)
+ char *one
+ char *two
+
+# create a new empty header
+# Is this usefull
+
+void
+headernew()
+ PREINIT:
+ Header h = headerNew();
+ PPCODE:
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)h)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, h, h->nrefs);
+#endif
+
+
+# Read data from file pointer and return next header object
+# Return undef if failed
+# fedora use HEADER_MAGIC_NO, too bad, set no_header_magic make the function
+# compatible
+void
+stream2header(fp, no_header_magic = 0, callback = NULL)
+ FILE *fp
+ int no_header_magic
+ SV * callback
+ PREINIT:
+ FD_t fd;
+ Header header;
+ PPCODE:
+ if (fp && (fd = fdDup(fileno(fp)))) {
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ if (callback != NULL && SvROK(callback)) {
+ while ((header = headerRead(fd, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES))) {
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)header)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, header, header->nrefs);
+#endif
+ PUTBACK;
+ call_sv(callback, G_DISCARD | G_SCALAR);
+ SPAGAIN;
+ FREETMPS;
+ LEAVE;
+ }
+ } else {
+ header = headerRead(fd, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES);
+ if (header) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)header)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, header, header->nrefs);
+#endif
+
+ }
+#ifdef HDLISTDEBUG
+ else fprintf(stderr, "HDEBUG: No header found from fp: %d\n", fileno(fp));
+#endif
+ }
+ Fclose(fd);
+ }
+
+# Read a rpm and return a Header
+# Return undef if failed
+void
+rpm2header(filename, sv_vsflags = NULL)
+ char * filename
+ SV * sv_vsflags
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ rpmVSFlags vsflags = RPMVSF_DEFAULT;
+ PPCODE:
+ if (sv_vsflags == NULL) /* Nothing has been passed, default is no signature */
+ vsflags |= _RPMVSF_NOSIGNATURES;
+ else
+ vsflags = sv2vsflags(sv_vsflags);
+ rpmtsSetVSFlags(ts, vsflags);
+ _rpm2header(ts, filename, 0);
+ SPAGAIN;
+ ts = rpmtsFree(ts);
+
+int
+rpmresign(passphrase, rpmfile)
+ char * passphrase
+ char * rpmfile
+ CODE:
+ RETVAL = rpmsign(passphrase, (const char *) rpmfile);
+ OUTPUT:
+ RETVAL
+
+void
+installsrpm(filename, sv_vsflags = NULL)
+ char * filename
+ SV * sv_vsflags
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ rpmVSFlags vsflags = RPMVSF_DEFAULT;
+ PPCODE:
+ vsflags = sv2vsflags(sv_vsflags);
+ rpmtsSetVSFlags(ts, vsflags);
+ PUTBACK;
+ _installsrpms(ts, filename);
+ SPAGAIN;
+ ts = rpmtsFree(ts);
+
+MODULE = RPM4 PACKAGE = RPM4::Header PREFIX = Header_
+
+void
+Header_DESTROY(h)
+ Header h
+ CODE:
+#ifdef HDRPMMEM
+ PRINTF_FREE(bless_header, h, h->nrefs);
+#endif
+ headerFree(h);
+
+# Write rpm header into file pointer
+# fedora use HEADER_MAGIC_NO, too bad, set no_header_magic make the function
+# compatible
+int
+Header_write(h, fp, no_header_magic = 0)
+ Header h
+ FILE * fp
+ int no_header_magic
+ PREINIT:
+ FD_t fd;
+ CODE:
+ RETVAL = 0;
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ if (h) {
+ if ((fd = fdDup(fileno(fp))) != NULL) {
+ headerWrite(fd, h, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES);
+ Fclose(fd);
+ RETVAL = 1;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Header_hsize(h, no_header_magic = 0)
+ Header h
+ int no_header_magic
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(headerSizeof(h, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES))));
+
+void
+Header_copy(h)
+ Header h
+ PREINIT:
+ Header hcopy;
+ PPCODE:
+ hcopy = headerCopy(h);
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)hcopy)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, hcopy, hcopy->nrefs);
+#endif
+
+void
+Header_string(h, no_header_magic = 0)
+ Header h
+ int no_header_magic
+ PREINIT:
+ char * string = NULL;
+ int offset = 0;
+ void * ptr = NULL;
+ int hsize = 0;
+ PPCODE:
+ ptr = headerUnload(h);
+ hsize = headerSizeof(h, no_header_magic ? HEADER_MAGIC_NO : HEADER_MAGIC_YES);
+ string = malloc(hsize);
+ if (!no_header_magic) {
+ memcpy(string, header_magic, sizeof(header_magic));
+ offset = sizeof(header_magic);
+ }
+ memcpy(string + offset, ptr, headerSizeof(h, HEADER_MAGIC_NO));
+ PUSHs(sv_2mortal(newSVpv((char *)string, hsize)));
+ free(ptr);
+
+
+int
+Header_removetag(h, sv_tag)
+ Header h
+ SV * sv_tag
+ PREINIT:
+ rpmTag tag = -1;
+ CODE:
+ if (SvIOK(sv_tag)) {
+ tag = SvIV(sv_tag);
+ } else if (SvPOK(sv_tag)) {
+ tag = tagValue(SvPV_nolen(sv_tag));
+ }
+ if (tag > 0)
+ RETVAL = headerRemoveEntry(h, tag);
+ else
+ RETVAL = 1;
+ OUTPUT:
+ RETVAL
+
+int
+Header_addtag(h, sv_tag, sv_tagtype, ...)
+ Header h
+ SV * sv_tag
+ SV * sv_tagtype
+ PREINIT:
+ char * value;
+ int ivalue;
+ int i;
+ rpmTag tag = -1;
+ rpmTagType tagtype = RPM_NULL_TYPE;
+ STRLEN len;
+ CODE:
+ if (SvIOK(sv_tag)) {
+ tag = SvIV(sv_tag);
+ } else if (SvPOK(sv_tag)) {
+ tag = tagValue(SvPV_nolen(sv_tag));
+ }
+ tagtype = sv2tagtype(sv_tagtype);
+ if (tag > 0)
+ RETVAL = 1;
+ else
+ RETVAL = 0;
+ if (tag == RPMTAG_OLDFILENAMES)
+ expandFilelist(h);
+ for (i = 3; (i < items) && RETVAL; i++) {
+ switch (tagtype) {
+ case RPM_CHAR_TYPE:
+ case RPM_INT8_TYPE:
+ case RPM_INT16_TYPE:
+ case RPM_INT32_TYPE:
+ ivalue = SvUV(ST(i));
+ RETVAL = headerAddOrAppendEntry(h, tag, tagtype, &ivalue, 1);
+ break;
+ case RPM_BIN_TYPE:
+ value = (char *)SvPV(ST(i), len);
+ RETVAL = headerAddEntry(h, tag, tagtype, value, len);
+ break;
+ case RPM_STRING_ARRAY_TYPE:
+ value = SvPV_nolen(ST(i));
+ RETVAL = headerAddOrAppendEntry(h, tag, tagtype, &value, 1);
+ break;
+ default:
+ value = SvPV_nolen(ST(i));
+ RETVAL = headerAddOrAppendEntry(h, tag, tagtype, value, 1);
+ break;
+ }
+ }
+ if (tag == RPMTAG_OLDFILENAMES) {
+ compressFilelist(h);
+ }
+ OUTPUT:
+ RETVAL
+
+void
+Header_listtag(h)
+ Header h
+ PREINIT:
+ HeaderIterator iterator;
+ int tag;
+ PPCODE:
+ iterator = headerInitIterator(h);
+ while (headerNextIterator(iterator, &tag, NULL, NULL, NULL)) {
+ XPUSHs(sv_2mortal(newSViv(tag)));
+ }
+ headerFreeIterator(iterator);
+
+int
+Header_hastag(h, sv_tag)
+ Header h
+ SV * sv_tag
+ PREINIT:
+ rpmTag tag = -1;
+ CODE:
+ if (SvIOK(sv_tag)) {
+ tag = SvIV(sv_tag);
+ } else if (SvPOK(sv_tag)) {
+ tag = tagValue(SvPV_nolen(sv_tag));
+ }
+ if (tag > 0)
+ RETVAL = headerIsEntry(h, tag);
+ else
+ RETVAL = -1;
+ OUTPUT:
+ RETVAL
+
+# Return the tag value in headers
+void
+Header_tag(h, sv_tag)
+ Header h
+ SV * sv_tag
+ PREINIT:
+ void *ret = NULL;
+ int type;
+ int n;
+ rpmTag tag = -1;
+ PPCODE:
+ if (SvIOK(sv_tag)) {
+ tag = SvIV(sv_tag);
+ } else if (SvPOK(sv_tag)) {
+ tag = tagValue(SvPV_nolen(sv_tag));
+ }
+ if (tag > 0)
+ if (headerGetEntry(h, tag, &type, &ret, &n)) {
+ switch(type) {
+ case RPM_STRING_ARRAY_TYPE:
+ {
+ int i;
+ char **s;
+
+ EXTEND(SP, n);
+ s = (char **)ret;
+
+ for (i = 0; i < n; i++) {
+ PUSHs(sv_2mortal(newSVpv(s[i], 0)));
+ }
+ }
+ break;
+ case RPM_STRING_TYPE:
+ PUSHs(sv_2mortal(newSVpv((char *)ret, 0)));
+ break;
+ case RPM_CHAR_TYPE:
+ case RPM_INT8_TYPE:
+ case RPM_INT16_TYPE:
+ case RPM_INT32_TYPE:
+ {
+ int i;
+ int *r;
+
+ EXTEND(SP, n);
+ r = (int *)ret;
+
+ for (i = 0; i < n; i++) {
+ PUSHs(sv_2mortal(newSViv(r[i])));
+ }
+ }
+ break;
+ case RPM_BIN_TYPE:
+ PUSHs(sv_2mortal(newSVpv((char *)ret, n)));
+ break;
+ default:
+ croak("unknown rpm tag type %d", type);
+ }
+ }
+ headerFreeTag(h, ret, type);
+
+int
+Header_tagtype(h, sv_tag)
+ Header h
+ SV * sv_tag
+ PREINIT:
+ int type;
+ rpmTag tag = -1;
+ CODE:
+ if (SvIOK(sv_tag)) {
+ tag = SvIV(sv_tag);
+ } else if (SvPOK(sv_tag)) {
+ tag = tagValue(SvPV_nolen(sv_tag));
+ }
+ RETVAL = RPM_NULL_TYPE;
+ if (tag > 0)
+ if (headerGetEntry(h, tag, &type, NULL, NULL))
+ RETVAL = type;
+ OUTPUT:
+ RETVAL
+
+void
+Header_queryformat(h, query)
+ Header h
+ char * query
+ PREINIT:
+ char *s = NULL;
+ PPCODE:
+ s = headerSprintf(h, query,
+ rpmTagTable, rpmHeaderFormats, NULL);
+ if (s) {
+ char * cs = NULL;
+ int len = strlen(s);
+
+ cs = malloc(strlen(s)); /* TODO need to check return of malloc */
+ memcpy(cs, s, len);
+ XPUSHs(sv_2mortal(newSVpv(cs, len)));
+ }
+ _free(s);
+
+void
+Header_fullname(h)
+ Header h
+ PREINIT:
+ I32 gimme = GIMME_V;
+ char *name;
+ char *version;
+ char *release;
+ char *arch;
+ PPCODE:
+ if (h) {
+ headerGetEntry(h, RPMTAG_NAME, NULL, (void *) &name, NULL);
+ headerGetEntry(h, RPMTAG_VERSION, NULL, (void *) &version, NULL);
+ headerGetEntry(h, RPMTAG_RELEASE, NULL, (void *) &release, NULL);
+ headerGetEntry(h, RPMTAG_ARCH, NULL, (void *) &arch, NULL);
+
+ if (gimme == G_SCALAR) {
+ XPUSHs(sv_2mortal(newSVpvf("%s-%s-%s.%s",
+ name,
+ version,
+ release,
+ headerIsEntry(h, RPMTAG_SOURCEPACKAGE) ? "src" : arch
+ )));
+ } else if (gimme == G_ARRAY) {
+ EXTEND(SP, 4);
+ PUSHs(sv_2mortal(newSVpv(name, 0)));
+ PUSHs(sv_2mortal(newSVpv(version, 0)));
+ PUSHs(sv_2mortal(newSVpv(release, 0)));
+ if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) {
+ PUSHs(sv_2mortal(newSVpv("src", 0)));
+ } else {
+ PUSHs(sv_2mortal(newSVpv(arch, 0)));
+ }
+ }
+ }
+ headerFreeTag(h, name, RPM_STRING_TYPE);
+ headerFreeTag(h, version, RPM_STRING_TYPE);
+ headerFreeTag(h, release, RPM_STRING_TYPE);
+ headerFreeTag(h, arch, RPM_STRING_TYPE);
+
+void
+Header_nevr(header)
+ Header header
+ PPCODE:
+ PUSHs(sv_2mortal(newSVpv(hGetNEVR(header, NULL), 0)));
+
+int
+Header_issrc(h)
+ Header h
+ CODE:
+ RETVAL = headerIsEntry(h, RPMTAG_SOURCEPACKAGE);
+ OUTPUT:
+ RETVAL
+
+# Dependancies versions functions
+
+int
+Header_compare(h1, h2)
+ Header h1
+ Header h2
+ CODE:
+ RETVAL = rpmVersionCompare(h1, h2);
+ OUTPUT:
+ RETVAL
+
+void
+Header_dep(header, type, scaremem = O_SCAREMEM)
+ Header header
+ SV * type
+ int scaremem
+ PREINIT:
+ rpmds ds;
+ rpmTag tag;
+ PPCODE:
+ tag = sv2deptag(type);
+ ds = rpmdsNew(header, tag, scaremem);
+ ds = rpmdsInit(ds);
+ if (ds != NULL)
+ if (rpmdsNext(ds) >= 0) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, ds)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmds, ds, ds->nrefs);
+#endif
+
+ }
+
+void
+Header_files(header, scaremem = O_SCAREMEM)
+ Header header
+ int scaremem
+ PREINIT:
+ rpmfi Files;
+ rpmts ts = NULL; /* setting this to NULL skip path relocation
+ * maybe a good deal is Header::Files(header, Dep = NULL) */
+ PPCODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ Files = rpmfiNew(ts, header, RPMTAG_BASENAMES, scaremem);
+ if ((Files = rpmfiInit(Files, 0)) != NULL && rpmfiNext(Files) >= 0) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmfi, Files)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmfi, Files, Files->nrefs);
+#endif
+ }
+
+void
+Header_hchkdep(h1, h2, type)
+ Header h1
+ Header h2
+ SV * type
+ PREINIT:
+ rpmds ds = NULL;
+ rpmds pro = NULL;
+ rpmTag tag;
+ PPCODE:
+ tag = sv2deptag(type);
+ ds = rpmdsNew(h1, tag, SCAREMEM);
+ pro = rpmdsNew(h2, RPMTAG_PROVIDENAME, SCAREMEM);
+#ifdef HDLISTDEBUG
+ fprintf(stderr, "HDEBUG: Header::hchkdep %d: %s vs %s %p\n", tag, hGetNEVR(h1, NULL), hGetNEVR(h2, NULL), ds);
+#endif
+ if (ds != NULL) {
+ rpmdsInit(ds);
+ while (rpmdsNext(ds) >= 0) {
+ rpmdsInit(pro);
+ while (rpmdsNext(pro) >= 0) {
+ if (rpmdsCompare(ds,pro)) {
+ XPUSHs(sv_2mortal(newSVpv(rpmdsDNEVR(ds), 0)));
+#ifdef HDLISTDEBUG
+ fprintf(stderr, "HDEBUG: Header::hchkdep match %s %s p in %s\n", rpmdsDNEVR(ds), rpmdsDNEVR(pro), hGetNEVR(h2, NULL));
+#endif
+ break;
+ }
+ }
+ }
+ }
+ pro = rpmdsFree(pro);
+ ds = rpmdsFree(ds);
+
+int
+Header_matchdep(header, Dep, sv_nopromote = NULL)
+ Header header
+ SV * sv_nopromote
+ rpmds Dep
+ PREINIT:
+ int nopromote = 0;
+ CODE:
+ if (sv_nopromote != NULL)
+ nopromote = SvIV(sv_nopromote);
+ RETVAL = _header_vs_dep(header, Dep, nopromote);
+ OUTPUT:
+ RETVAL
+
+int
+Header_namematchdep(header, Dep, sv_nopromote = NULL)
+ Header header
+ rpmds Dep
+ SV * sv_nopromote
+ PREINIT:
+ int nopromote = 0;
+ CODE:
+ if (sv_nopromote != NULL)
+ nopromote = SvIV(sv_nopromote);
+ RETVAL = _headername_vs_dep(header, Dep, nopromote); /* return 1 if match */
+ OUTPUT:
+ RETVAL
+
+# DB functions
+MODULE = RPM4 PACKAGE = RPM4
+
+int
+rpmdbinit(rootdir = NULL)
+ char * rootdir
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ CODE:
+ if (rootdir)
+ rpmtsSetRootDir(ts, rootdir);
+ /* rpm{db,ts}init is deprecated, we open a database with create flags
+ * and close it */
+ /* 0 on success */
+ RETVAL = rpmtsOpenDB(ts, O_CREAT);
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+int
+rpmdbverify(rootdir = NULL)
+ char * rootdir
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ CODE:
+ if (rootdir)
+ rpmtsSetRootDir(ts, rootdir);
+ /* 0 on success */
+ RETVAL = rpmtsVerifyDB(ts);
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+int
+rpmdbrebuild(rootdir = NULL)
+ char * rootdir
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ CODE:
+ if (rootdir)
+ rpmtsSetRootDir(ts, rootdir);
+ /* 0 on success */
+ RETVAL = rpmtsRebuildDB(ts);
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+#ifdef HHACK
+void
+emptydb()
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ PPCODE:
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmts, (void *)ts)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmts, ts, ts->nrefs);
+#endif
+
+
+#endif
+
+void
+newdb(write = 0, rootdir = NULL)
+ int write
+ char * rootdir
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ PPCODE:
+ if (rootdir)
+ rpmtsSetRootDir(ts, rootdir);
+
+ rpmtsSetVSFlags(ts, RPMTRANS_FLAG_NONE);
+ /* is O_CREAT a good idea here ? */
+ /* is the rpmtsOpenDB really need ? */
+ if (rpmtsOpenDB(ts, write ? O_RDWR | O_CREAT : O_RDONLY) == 0) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmts, (void *)ts)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmts, ts, ts->nrefs);
+#endif
+ } else {
+ ts = rpmtsFree(ts);
+ }
+
+MODULE = RPM4 PACKAGE = RPM4::Transaction PREFIX = Ts_
+
+void
+Ts_new(perlclass, rootdir = NULL)
+ char * perlclass
+ char * rootdir
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ PPCODE:
+ if (rootdir)
+ rpmtsSetRootDir(ts, rootdir);
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), perlclass, (void *)ts)));
+
+void
+Ts_DESTROY(ts)
+ rpmts ts
+ CODE:
+#ifdef HDRPMMEM
+ PRINTF_FREE(bless_rpmts, ts, ts->nrefs);
+#endif
+ ts = rpmtsFree(ts);
+
+# Function to control RPM4::Transaction behaviour
+
+int
+Ts_vsflags(ts, sv_vsflags = NULL)
+ rpmts ts
+ SV * sv_vsflags
+ PREINIT:
+ rpmVSFlags vsflags;
+ CODE:
+ if (sv_vsflags != NULL) {
+ vsflags = sv2vsflags(sv_vsflags);
+ RETVAL = rpmtsSetVSFlags(ts, vsflags);
+ } else {
+ RETVAL = rpmtsVSFlags(ts);
+ }
+ OUTPUT:
+ RETVAL
+
+int
+Ts_transflag(ts, sv_transflag = NULL)
+ rpmts ts
+ SV * sv_transflag
+ PREINIT:
+ rpmtransFlags transflags;
+ CODE:
+ if (sv_transflag != NULL) {
+ transflags = sv2transflags(sv_transflag);
+ /* Take care to rpm config (userland) */
+ if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
+ transflags |= RPMTRANS_FLAG_REPACKAGE;
+ RETVAL = rpmtsSetFlags(ts, transflags);
+ } else {
+ RETVAL = rpmtsFlags(ts);
+ }
+ OUTPUT:
+ RETVAL
+
+int
+Ts_injectheader(db, header)
+ rpmts db
+ Header header
+ PREINIT:
+ rpmdb rdb;
+ CODE:
+ rdb = rpmtsGetRdb(db);
+ RETVAL = rpmdbAdd(rdb, 0, header, db, NULL);
+ OUTPUT:
+ RETVAL
+
+int
+Ts_deleteheader(db, sv_offset)
+ rpmts db
+ SV * sv_offset
+ PREINIT:
+ rpmdb rdb;
+ unsigned int offset = 0;
+ CODE:
+ offset = SvUV(sv_offset);
+ rdb = rpmtsGetRdb(db);
+ if (offset)
+ RETVAL = rpmdbRemove(rdb, 0, offset, db, NULL);
+ else
+ RETVAL = 1;
+ OUTPUT:
+ RETVAL
+
+int
+Ts_traverse(ts, callback = NULL, sv_tagname = NULL, sv_tagvalue = NULL, keylen = 0, sv_exclude = NULL)
+ rpmts ts
+ SV * callback
+ SV * sv_tagname
+ SV * sv_tagvalue
+ SV * sv_exclude
+ int keylen
+ PREINIT:
+ rpmTag tag;
+ void * value = NULL;
+ rpmdbMatchIterator mi;
+ Header header;
+ int rc = 1;
+ int count = 0;
+ int * exclude = NULL;
+ AV * av_exclude;
+ int i;
+ CODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ ts = rpmtsLink(ts, "RPM4 Db::traverse()");
+ if (sv_tagname == NULL || !SvOK(sv_tagname)) {
+ tag = RPMDBI_PACKAGES; /* Assume search into installed packages */
+ } else {
+ tag = sv2dbquerytag(sv_tagname);
+ }
+ if (sv_tagvalue != NULL && SvOK(sv_tagvalue)) {
+ switch (tag) {
+ case RPMDBI_PACKAGES:
+ i = SvIV(sv_tagvalue);
+ value = &i;
+ keylen = sizeof(i);
+ break;
+ default:
+ value = (void *) SvPV_nolen(sv_tagvalue);
+ break;
+ }
+ }
+
+ RETVAL = 0;
+ if (tag >= 0) {
+ mi = rpmtsInitIterator(ts, tag, value, keylen);
+ if (sv_exclude != NULL && SvOK(sv_exclude) && SvTYPE(SvRV(sv_exclude)) == SVt_PVAV) {
+ av_exclude = (AV*)SvRV(sv_exclude);
+ exclude = malloc((av_len(av_exclude)+1) * sizeof(int));
+ for (i = 0; i <= av_len(av_exclude); i++) {
+ SV **isv = av_fetch(av_exclude, i, 0);
+ exclude[i] = SvUV(*isv);
+ }
+ rpmdbPruneIterator(mi, exclude, av_len(av_exclude) + 1, 0);
+ }
+ while (rc && ((header = rpmdbNextIterator(mi)) != NULL)) {
+ RETVAL++;
+ if (callback != NULL && SvROK(callback)) {
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, headerLink(header))));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, header, header->nrefs);
+#endif
+ XPUSHs(sv_2mortal(newSVuv(rpmdbGetIteratorOffset(mi))));
+ PUTBACK;
+ count = call_sv(callback, G_SCALAR);
+ SPAGAIN;
+ if (tag == RPMDBI_PACKAGES && value != NULL) {
+ rc = 0;
+ } else if (count == 1) {
+ rc = POPi;
+ }
+ FREETMPS;
+ LEAVE;
+
+ }
+ }
+ if (exclude != NULL) free(exclude);
+ rpmdbFreeIterator(mi);
+ } else
+ RETVAL = -1;
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+void
+Ts_get_header(ts, off)
+ rpmts ts
+ int off
+ PREINIT:
+ rpmdbMatchIterator mi;
+ Header header;
+ PPCODE:
+ mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &off, sizeof(off));
+ if ((header = rpmdbNextIterator(mi)) != NULL) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, headerLink(header))));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_header, header, header->nrefs);
+#endif
+ }
+ rpmdbFreeIterator(mi);
+
+int
+Ts_transadd(ts, header, key = NULL, upgrade = 1, sv_relocation = NULL, force = 0)
+ rpmts ts
+ Header header
+ char * key
+ int upgrade
+ SV * sv_relocation
+ int force
+ PREINIT:
+ rpmRelocation * relocations = NULL;
+ HV * hv_relocation;
+ HE * he_relocation;
+ int i = 0;
+ I32 len;
+ CODE:
+
+ if (key != NULL)
+ key = strdup(key);
+
+ /* Relocation settings */
+ if (sv_relocation && SvOK(sv_relocation) && !force) {
+/* if (! (headerGetEntry(eiu->h, RPMTAG_PREFIXES, &pft,
+ (void **) &paths, &c) && (c == 1))) { */
+ if (! headerIsEntry(header, RPMTAG_PREFIXES)) {
+ rpmMessage(RPMMESS_ERROR,
+ _("package %s is not relocatable\n"), "");
+ XPUSHi((IV)1);
+ XSRETURN(1);
+ }
+ if (SvTYPE(sv_relocation) == SVt_PV) {
+ /* String value, assume a prefix */
+ relocations = malloc(2 * sizeof(*relocations));
+ relocations[0].oldPath = NULL;
+ relocations[0].newPath = SvPV_nolen(sv_relocation);
+ relocations[1].oldPath = relocations[1].newPath = NULL;
+ } else if (SvTYPE(SvRV(sv_relocation)) == SVt_PVHV) {
+ hv_relocation = (HV*)SvRV(sv_relocation);
+ hv_iterinit(hv_relocation);
+ while ((he_relocation = hv_iternext(hv_relocation)) != NULL) {
+ relocations = realloc(relocations, sizeof(*relocations) * (++i));
+ relocations[i-1].oldPath = NULL;
+ relocations[i-1].newPath = NULL;
+ relocations[i-1].oldPath = hv_iterkey(he_relocation, &len);
+ relocations[i-1].newPath = SvPV_nolen(hv_iterval(hv_relocation, he_relocation));
+ }
+ /* latest relocation is identify by NULL setting */
+ relocations = realloc(relocations, sizeof(*relocations) * (++i));
+ relocations[i-1].oldPath = relocations[i-1].newPath = NULL;
+ } else {
+ croak("latest argument is set but is not an array ref or a string");
+ }
+ }
+
+ /* TODO fnpyKey: another value can be use... */
+ RETVAL = rpmtsAddInstallElement(ts, header, (fnpyKey) key, upgrade, relocations);
+ OUTPUT:
+ RETVAL
+
+int
+Ts_transremove(ts, recOffset, header = NULL)
+ rpmts ts
+ int recOffset
+ Header header
+ PREINIT:
+ rpmdbMatchIterator mi;
+ CODE:
+ RETVAL = 0;
+ if (header != NULL) { /* reprofit Db_traverse */
+ rpmtsAddEraseElement(ts, header, recOffset);
+ } else {
+ mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
+ if ((header = rpmdbNextIterator(mi)) != NULL) {
+#ifdef HDLISTDEBUG
+ fprintf(stderr, "HDEBUG: Db::transremove(h, o) H: %p Off:%u\n", header, recOffset);
+#endif
+ rpmtsAddEraseElement(ts, header, recOffset);
+ RETVAL = 1;
+ }
+ rpmdbFreeIterator(mi);
+ }
+ OUTPUT:
+ RETVAL
+
+int
+Ts_transremove_pkg(ts, N_evr)
+ rpmts ts
+ char * N_evr
+ PREINIT:
+ rpmdbMatchIterator mi;
+ Header header;
+ int recOffset;
+ CODE:
+ RETVAL = 0;
+ /* N_evr is not NEVR but N(EVR), with RPMDBI_LABEL
+ * I want to find another way to exactly match a header
+ * For more flexible function, check Db_traverse / Db_transremove */
+ mi = rpmtsInitIterator(ts, RPMDBI_LABEL, N_evr, 0);
+ while ((header = rpmdbNextIterator(mi))) {
+ recOffset = rpmdbGetIteratorOffset(mi);
+#ifdef HDLISTDEBUG
+ fprintf(stderr, "HDEBUG: Db::transremove(Name) N: %s H: %p Off:%u\n", N_evr, header, recOffset);
+#endif
+ if (recOffset != 0) {
+ rpmtsAddEraseElement(ts, header, recOffset);
+ RETVAL ++;
+ }
+ }
+ rpmdbFreeIterator(mi);
+ OUTPUT:
+ RETVAL
+
+int
+Ts_traverse_transaction(ts, callback, type = 0)
+ rpmts ts
+ SV * callback
+ int type
+ PREINIT:
+ rpmtsi pi;
+ rpmte Te;
+ CODE:
+ ts = rpmtsLink(ts, "RPM4 Db::traverse_transaction()");
+ pi = rpmtsiInit(ts);
+ RETVAL = 0;
+ while ((Te = rpmtsiNext(pi, type)) != NULL) {
+ RETVAL++;
+ if (callback != NULL && SvROK(callback)) {
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), "RPM4::Db::Te", Te)));
+ PUTBACK;
+ call_sv(callback, G_DISCARD | G_SCALAR);
+ SPAGAIN;
+ FREETMPS;
+ LEAVE;
+ }
+ }
+ pi = rpmtsiFree(pi);
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+int
+Ts_transcheck(ts, callback = NULL)
+ rpmts ts
+ SV * callback
+ CODE:
+ ts = rpmtsLink(ts, "RPM4 Db_transcheck()");
+ if (callback != NULL && SvOK(callback) && SvTYPE(SvRV(callback)) == SVt_PVCV) { /* Be sure we have a code ref */
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ rpmtsSetSolveCallback(ts, transSolveCallback, (void *) callback);
+ }
+
+ RETVAL = rpmtsCheck(ts);
+ /* Restoring default rpm setting */
+ rpmtsSetSolveCallback(ts, rpmtsSolve, NULL);
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+int
+Ts_transorder(ts)
+ rpmts ts
+ CODE:
+ RETVAL = rpmtsOrder(ts);
+ OUTPUT:
+ RETVAL
+
+void
+Ts_transclean(ts)
+ rpmts ts
+ PPCODE:
+ rpmtsClean(ts);
+
+int
+Ts_transrun(ts, callback, ...)
+ rpmts ts
+ SV * callback
+ PREINIT:
+ int i;
+ rpmprobFilterFlags probFilter = RPMPROB_FILTER_NONE;
+ rpmInstallInterfaceFlags install_flags = INSTALL_NONE;
+ rpmps ps;
+ CODE:
+ ts = rpmtsLink(ts, "RPM4 Db::transrun()");
+ if (!SvOK(callback)) { /* undef value */
+ rpmtsSetNotifyCallback(ts,
+ rpmShowProgress,
+ (void *) ((long) INSTALL_LABEL | INSTALL_HASH | INSTALL_UPGRADE));
+ } else if (SvTYPE(SvRV(callback)) == SVt_PVCV) { /* ref sub */
+ rpmtsSetNotifyCallback(ts,
+ transCallback, (void *) callback);
+ } else if (SvTYPE(SvRV(callback)) == SVt_PVAV) { /* array ref */
+ install_flags = sv2constant(callback, "rpminstallinterfaceflags");
+ rpmtsSetNotifyCallback(ts,
+ rpmShowProgress,
+ (void *) ((long) install_flags));
+ } else {
+ croak("Wrong parameter given");
+ }
+
+ for (i = 2; i < items; i++)
+ probFilter |= sv2constant(ST(i), "rpmprobfilterflags");
+
+ ps = rpmtsProblems(ts);
+ RETVAL = rpmtsRun(ts, ps, probFilter);
+ ps = rpmpsFree(ps);
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+# get from transaction a problem set
+void
+Ts__transpbs(ts)
+ rpmts ts
+ PREINIT:
+ rpmps ps;
+ PPCODE:
+ ps = rpmtsProblems(ts);
+ if (ps && ps->numProblems) /* if no problem, return undef */
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmps, ps)));
+
+int
+Ts_importpubkey(ts, filename)
+ rpmts ts
+ char * filename
+ PREINIT:
+ const byte * pkt = NULL;
+ size_t pktlen = 0;
+ int rc;
+ CODE:
+ rpmtsClean(ts);
+
+ if ((rc = pgpReadPkts(filename, &pkt, &pktlen)) <= 0) {
+ RETVAL = 1;
+ } else if (rc != PGPARMOR_PUBKEY) {
+ RETVAL = 1;
+ } else if (rpmcliImportPubkey(ts, pkt, pktlen) != RPMRC_OK) {
+ RETVAL = 1;
+ } else {
+ RETVAL = 0;
+ }
+ pkt = _free(pkt);
+ OUTPUT:
+ RETVAL
+
+void
+Ts_checkrpm(ts, filename, sv_vsflags = NULL)
+ rpmts ts
+ char * filename
+ SV * sv_vsflags
+ PREINIT:
+ rpmVSFlags vsflags = RPMVSF_DEFAULT;
+ rpmVSFlags oldvsflags = RPMVSF_DEFAULT;
+ PPCODE:
+ oldvsflags = rpmtsVSFlags(ts); /* keep track of old settings */
+ if (sv_vsflags != NULL) {
+ vsflags = sv2vsflags(sv_vsflags);
+ rpmtsSetVSFlags(ts, vsflags);
+ }
+ PUTBACK;
+ _rpm2header(ts, filename, 1); /* Rpmread header is not the most usefull,
+ * but no other function in rpmlib allow this :( */
+ SPAGAIN;
+ rpmtsSetVSFlags(ts, oldvsflags); /* resetting in case of change */
+
+void
+Ts_transreset(ts)
+ rpmts ts
+ PPCODE:
+ rpmtsEmpty(ts);
+
+# Remaping function:
+
+# RPM4::rpm2header(filename); # Reusing existing RPM4::Db
+void
+Ts_rpm2header(ts, filename)
+ rpmts ts
+ char * filename
+ PPCODE:
+ _rpm2header(ts, filename, 0);
+ SPAGAIN;
+
+# RPM4::Spec::specbuild([ buildflags ]); Reusing existing RPM4::Db
+int
+Ts_specbuild(ts, spec, sv_buildflags)
+ rpmts ts
+ Spec spec
+ SV * sv_buildflags
+ CODE:
+ RETVAL = _specbuild(ts, spec, sv_buildflags);
+ OUTPUT:
+ RETVAL
+
+void
+Ts_installsrpm(ts, filename)
+ rpmts ts
+ char * filename
+ PPCODE:
+ PUTBACK;
+ _installsrpms(ts, filename);
+ SPAGAIN;
+
+MODULE = RPM4 PACKAGE = RPM4::Db::Te PREFIX = Te_
+
+void
+Te_DESTROY(Te)
+ rpmte Te
+ CODE:
+#ifdef HDRPMMEM
+/* PRINTF_FREE(RPM4::Db::Te, -1); */
+#endif
+ /* Don't do that ! *
+ Te = rpmteFree(Te); */
+
+int
+Te_type(Te)
+ rpmte Te
+ CODE:
+ RETVAL = rpmteType(Te);
+ OUTPUT:
+ RETVAL
+
+void
+Te_name(Te)
+ rpmte Te
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmteN(Te), 0)));
+
+void
+Te_version(Te)
+ rpmte Te
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmteV(Te), 0)));
+
+void
+Te_release(Te)
+ rpmte Te
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmteR(Te), 0)));
+
+void
+Te_epoch(Te)
+ rpmte Te
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmteE(Te), 0)));
+
+void
+Te_arch(Te)
+ rpmte Te
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmteA(Te), 0)));
+
+void
+Te_os(Te)
+ rpmte Te
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmteO(Te), 0)));
+
+void
+Te_fullname(Te)
+ rpmte Te
+ PREINIT:
+ I32 gimme = GIMME_V;
+ PPCODE:
+ if (gimme == G_SCALAR) {
+ XPUSHs(sv_2mortal(newSVpvf("%s-%s-%s.%s",
+ rpmteN(Te), rpmteV(Te), rpmteR(Te), rpmteA(Te))));
+ } else {
+ XPUSHs(sv_2mortal(newSVpv(rpmteN(Te), 0)));
+ XPUSHs(sv_2mortal(newSVpv(rpmteV(Te), 0)));
+ XPUSHs(sv_2mortal(newSVpv(rpmteR(Te), 0)));
+ XPUSHs(sv_2mortal(newSVpv(rpmteA(Te), 0)));
+ }
+
+void
+Te_size(Te)
+ rpmte Te
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVuv(rpmtePkgFileSize(Te))));
+
+void
+Te_dep(Te, type)
+ rpmte Te
+ SV * type
+ PREINIT:
+ rpmds ds;
+ rpmTag tag;
+ PPCODE:
+ tag = sv2deptag(type);
+ ds = rpmteDS(Te, tag);
+ if (ds != NULL)
+ if (rpmdsNext(ds) >= 0) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, ds)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmds, ds, ds->nrefs);
+#endif
+ }
+
+void
+Te_files(Te)
+ rpmte Te
+ PREINIT:
+ rpmfi Files;
+ PPCODE:
+ Files = rpmteFI(Te, RPMTAG_BASENAMES);
+ if ((Files = rpmfiInit(Files, 0)) != NULL && rpmfiNext(Files) >= 0) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmfi, Files)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmfi, Files, Files->nrefs);
+#endif
+ }
+
+MODULE = RPM4 PACKAGE = RPM4
+
+# Return a new Dep object
+void
+newdep(sv_depTag, Name, sv_sense = NULL, sv_evr = NULL)
+ SV * sv_depTag
+ char * Name
+ SV * sv_evr
+ SV * sv_sense
+ PPCODE:
+ PUTBACK;
+ _newdep(sv_depTag, Name, sv_sense, sv_evr);
+ SPAGAIN;
+
+void
+rpmlibdep()
+ PREINIT:
+ rpmds Dep = NULL;
+ rpmds next;
+ const char ** provNames;
+ int * provFlags;
+ const char ** provVersions;
+ int num = 0;
+ int i;
+ PPCODE:
+ num = rpmGetRpmlibProvides(&provNames, &provFlags, &provVersions);
+ for (i = 0; i < num; i++) {
+#ifdef HDLISTDEBUG
+ fprintf(stderr, "HDEBUG: rpmlibdep %s %s %d\n", provNames[i], provVersions[i], provFlags[i]);
+#endif
+ next = rpmdsSingle(RPMTAG_PROVIDENAME, provNames[i], provVersions[i], provFlags[i]);
+ rpmdsMerge(&Dep, next);
+ next = rpmdsFree(next);
+ }
+ if (Dep != NULL) {
+ Dep = rpmdsInit(Dep);
+ if (rpmdsNext(Dep) >= 0) {
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmds, Dep)));
+#ifdef HDRPMMEM
+ PRINTF_NEW(bless_rpmds, Dep, Dep->nrefs);
+#endif
+ }
+ }
+
+MODULE = RPM4 PACKAGE = RPM4::Header::Dependencies PREFIX = Dep_
+
+void
+Dep_newsingle(perlclass, sv_tag, name, sv_sense = NULL, sv_evr = NULL)
+ char * perlclass
+ SV * sv_tag
+ char * name
+ SV * sv_sense
+ SV * sv_evr
+ PPCODE:
+ PUTBACK;
+ _newdep(sv_tag, name, sv_sense, sv_evr);
+ SPAGAIN;
+
+void
+Dep_DESTROY(Dep)
+ rpmds Dep
+ CODE:
+#ifdef HDRPMMEM
+ PRINTF_FREE(bless_rpmds, Dep, Dep->nrefs);
+#endif
+ Dep = rpmdsFree(Dep);
+
+int
+Dep_count(Dep)
+ rpmds Dep
+ CODE:
+ RETVAL = rpmdsCount(Dep);
+ OUTPUT:
+ RETVAL
+
+int
+Dep_move(Dep, index = 0)
+ rpmds Dep
+ int index
+ CODE:
+ if (index == -1) /* -1 do nothing and give actual index */
+ RETVAL = rpmdsIx(Dep);
+ else
+ RETVAL = rpmdsSetIx(Dep, index);
+ OUTPUT:
+ RETVAL
+
+void
+Dep_init(Dep)
+ rpmds Dep
+ CODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ rpmdsInit(Dep);
+
+int
+Dep_next(Dep)
+ rpmds Dep
+ CODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ RETVAL = rpmdsNext(Dep);
+ OUTPUT:
+ RETVAL
+
+int
+Dep_hasnext(Dep)
+ rpmds Dep
+ CODE:
+ RETVAL = rpmdsNext(Dep) > -1;
+ OUTPUT:
+ RETVAL
+
+int
+Dep_color(Dep)
+ rpmds Dep
+ CODE:
+ RETVAL = rpmdsColor(Dep);
+ OUTPUT:
+ RETVAL
+
+int
+Dep_find(Dep, depb)
+ rpmds Dep
+ rpmds depb
+ CODE:
+ RETVAL = rpmdsFind(Dep, depb);
+ OUTPUT:
+ RETVAL
+
+int
+Dep_merge(Dep, depb)
+ rpmds Dep
+ rpmds depb
+ CODE:
+ RETVAL = rpmdsMerge(&Dep, depb);
+ OUTPUT:
+ RETVAL
+
+int
+Dep_overlap(Dep1, Dep2)
+ rpmds Dep1
+ rpmds Dep2
+ CODE:
+ CHECK_RPMDS_IX(Dep1);
+ CHECK_RPMDS_IX(Dep2);
+ RETVAL = rpmdsCompare(Dep1, Dep2);
+ OUTPUT:
+ RETVAL
+
+void
+Dep_info(Dep)
+ rpmds Dep
+ PREINIT:
+ rpmsenseFlags flag;
+ I32 gimme = GIMME_V;
+ PPCODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ CHECK_RPMDS_IX(Dep);
+ if (gimme == G_SCALAR) {
+ XPUSHs(sv_2mortal(newSVpv(rpmdsDNEVR(Dep), 0)));
+ } else {
+ switch (rpmdsTagN(Dep)) {
+ case RPMTAG_PROVIDENAME:
+ XPUSHs(sv_2mortal(newSVpv("P", 0)));
+ break;
+ case RPMTAG_REQUIRENAME:
+ XPUSHs(sv_2mortal(newSVpv("R", 0)));
+ break;
+ case RPMTAG_CONFLICTNAME:
+ XPUSHs(sv_2mortal(newSVpv("C", 0)));
+ break;
+ case RPMTAG_OBSOLETENAME:
+ XPUSHs(sv_2mortal(newSVpv("O", 0)));
+ break;
+ case RPMTAG_TRIGGERNAME:
+ XPUSHs(sv_2mortal(newSVpv("T", 0)));
+ break;
+ default:
+ break;
+ }
+ XPUSHs(sv_2mortal(newSVpv(rpmdsN(Dep), 0)));
+ flag = rpmdsFlags(Dep);
+ XPUSHs(sv_2mortal(newSVpvf("%s%s%s",
+ flag & RPMSENSE_LESS ? "<" : "",
+ flag & RPMSENSE_GREATER ? ">" : "",
+ flag & RPMSENSE_EQUAL ? "=" : "")));
+ XPUSHs(sv_2mortal(newSVpv(rpmdsEVR(Dep), 0)));
+ }
+
+void
+Dep_tag(Dep)
+ rpmds Dep
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmdsTagN(Dep))));
+
+void
+Dep_name(Dep)
+ rpmds Dep
+ PPCODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ CHECK_RPMDS_IX(Dep);
+ XPUSHs(sv_2mortal(newSVpv(rpmdsN(Dep), 0)));
+
+void
+Dep_flags(Dep)
+ rpmds Dep
+ PPCODE:
+ CHECK_RPMDS_IX(Dep);
+ XPUSHs(sv_2mortal(newSViv(rpmdsFlags(Dep))));
+
+void
+Dep_evr(Dep)
+ rpmds Dep
+ PPCODE:
+ CHECK_RPMDS_IX(Dep);
+ XPUSHs(sv_2mortal(newSVpv(rpmdsEVR(Dep), 0)));
+
+int
+Dep_nopromote(Dep, sv_nopromote = NULL)
+ rpmds Dep
+ SV * sv_nopromote
+ CODE:
+ if (sv_nopromote == NULL) {
+ RETVAL = rpmdsNoPromote(Dep);
+ } else {
+ RETVAL = rpmdsSetNoPromote(Dep, SvIV(sv_nopromote));
+ }
+ OUTPUT:
+ RETVAL
+
+
+int
+Dep_add(Dep, name, sv_sense = NULL, sv_evr = NULL)
+ rpmds Dep
+ char * name
+ SV * sv_evr
+ SV * sv_sense
+ PREINIT:
+ rpmsenseFlags sense = RPMSENSE_ANY;
+ rpmds Deptoadd;
+ char * evr = NULL;
+ CODE:
+ RETVAL = 0;
+ if (sv_sense && SvOK(sv_sense))
+ sense = sv2sens(sv_sense);
+ if (sv_evr && SvOK(sv_evr))
+ evr = SvPV_nolen(sv_evr);
+ Deptoadd = rpmdsSingle(rpmdsTagN(Dep), name,
+ evr ? evr : "", sense);
+ if (Deptoadd) {
+ rpmdsMerge(&Dep, Deptoadd);
+ Deptoadd = rpmdsFree(Deptoadd);
+ RETVAL = 1;
+ }
+ OUTPUT:
+ RETVAL
+
+int
+Dep_matchheader(Dep, header, sv_nopromote = NULL)
+ Header header
+ SV * sv_nopromote
+ rpmds Dep
+ PREINIT:
+ int nopromote = 0;
+ CODE:
+ if (sv_nopromote != NULL)
+ nopromote = SvIV(sv_nopromote);
+ RETVAL = _header_vs_dep(header, Dep, nopromote);
+ OUTPUT:
+ RETVAL
+
+int
+Dep_matchheadername(Dep, header, sv_nopromote = NULL)
+ rpmds Dep
+ Header header
+ SV * sv_nopromote
+ PREINIT:
+ int nopromote = 0;
+ CODE:
+ if (sv_nopromote != NULL)
+ nopromote = SvIV(sv_nopromote);
+ RETVAL = _headername_vs_dep(header, Dep, nopromote);
+ OUTPUT:
+ RETVAL
+
+MODULE = RPM4 PACKAGE = RPM4::Header::Files PREFIX = Files_
+
+void
+Files_DESTROY(Files)
+ rpmfi Files
+ PPCODE:
+#ifdef HDRPMMEM
+ PRINTF_FREE(bless_rpmfi, Files, Files->nrefs);
+#endif
+ Files = rpmfiFree(Files);
+
+int
+Files_compare(Files, Fb)
+ rpmfi Files
+ rpmfi Fb
+ CODE:
+ RETVAL = rpmfiCompare(Files, Fb);
+ OUTPUT:
+ RETVAL
+
+int
+Files_move(Files, index = 0)
+ rpmfi Files;
+ int index
+ PREINIT:
+ int i;
+ CODE:
+ index ++; /* keeping same behaviour than Header::Dep */
+ rpmfiInit(Files, 0);
+ RETVAL = 0;
+ for (i=-1; i < index && (RETVAL = rpmfiNext(Files)) >= 0; i++) {}
+ if (RETVAL == -1) {
+ rpmfiInit(Files, 0);
+ rpmfiNext(Files);
+ }
+ OUTPUT:
+ RETVAL
+
+int
+Files_count(Files)
+ rpmfi Files
+ CODE:
+ RETVAL = rpmfiFC(Files);
+ OUTPUT:
+ RETVAL
+
+int
+Files_countdir(Files)
+ rpmfi Files
+ CODE:
+ RETVAL = rpmfiDC(Files);
+ OUTPUT:
+ RETVAL
+
+void
+Files_init(Files)
+ rpmfi Files
+ CODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ rpmfiInit(Files, 0);
+
+void
+Files_initdir(Files)
+ rpmfi Files
+ CODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ rpmfiInitD(Files, 0);
+
+int
+Files_next(Files)
+ rpmfi Files
+ CODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ RETVAL = rpmfiNext(Files);
+ OUTPUT:
+ RETVAL
+
+int
+Files_hasnext(Files)
+ rpmfi Files
+ CODE:
+ RETVAL = rpmfiNext(Files) > -1;
+ OUTPUT:
+ RETVAL
+
+int
+Files_nextdir(Files)
+ rpmfi Files
+ CODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+#endif
+ RETVAL = rpmfiNextD(Files);
+ OUTPUT:
+ RETVAL
+
+void
+Files_filename(Files)
+ rpmfi Files
+ PPCODE:
+#ifdef HDLISTDEBUG
+ PRINTF_CALL;
+ fprintf(stderr, "File %s", rpmfiFN(Files));
+#endif
+ XPUSHs(sv_2mortal(newSVpv(rpmfiFN(Files), 0)));
+
+void
+Files_dirname(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmfiDN(Files), 0)));
+
+void
+Files_basename(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmfiBN(Files), 0)));
+
+void
+Files_fflags(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFFlags(Files))));
+
+void
+Files_mode(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFMode(Files))));
+
+void
+Files_md5(Files)
+ rpmfi Files
+ PREINIT:
+ const byte * md5;
+ char * fmd5 = malloc((char) 33);
+ PPCODE:
+ if ((md5 = rpmfiMD5(Files)) != NULL && *md5 != 0 /* return undef if empty */) {
+ (void) pgpHexCvt(fmd5, md5, 16);
+ XPUSHs(sv_2mortal(newSVpv(fmd5, 0)));
+ }
+ _free(fmd5);
+
+void
+Files_link(Files)
+ rpmfi Files
+ PREINIT:
+ const char * link;
+ PPCODE:
+ if ((link = rpmfiFLink(Files)) != NULL && *link != 0 /* return undef if empty */) {
+ XPUSHs(sv_2mortal(newSVpv(link, 0)));
+ }
+
+void
+Files_user(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmfiFUser(Files), 0)));
+
+void
+Files_group(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSVpv(rpmfiFGroup(Files), 0)));
+
+void
+Files_inode(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFInode(Files))));
+
+void
+Files_size(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFSize(Files))));
+
+void
+Files_dev(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFRdev(Files))));
+
+void
+Files_color(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFColor(Files))));
+
+void
+Files_class(Files)
+ rpmfi Files
+ PREINIT:
+ const char * class;
+ PPCODE:
+ if ((class = rpmfiFClass(Files)) != NULL)
+ XPUSHs(sv_2mortal(newSVpv(rpmfiFClass(Files), 0)));
+
+void
+Files_mtime(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFMtime(Files))));
+
+void
+Files_nlink(Files)
+ rpmfi Files
+ PPCODE:
+ XPUSHs(sv_2mortal(newSViv(rpmfiFNlink(Files))));
+
+MODULE = RPM4 PACKAGE = RPM4
+
+void
+newspec(filename = NULL, passphrase = NULL, rootdir = NULL, cookies = NULL, anyarch = NULL, force = NULL)
+ char * filename
+ SV * passphrase
+ SV * rootdir
+ SV * cookies
+ SV * anyarch
+ SV * force
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ PPCODE:
+ PUTBACK;
+ _newspec(ts, filename, passphrase, rootdir, cookies, anyarch, force);
+ ts = rpmtsFree(ts);
+ SPAGAIN;
+
+MODULE = RPM4 PACKAGE = RPM4::Spec PREFIX = Spec_
+
+void
+Spec_new(perlclass, specfile = NULL, ...)
+ char * perlclass
+ char * specfile
+ PREINIT:
+ rpmts ts = NULL;
+ SV * passphrase = NULL;
+ SV * rootdir = NULL;
+ SV * cookies = NULL;
+ SV * anyarch = 0;
+ SV * force = 0;
+ int i;
+ PPCODE:
+ for(i=2; i < items; i++) {
+ if(strcmp(SvPV_nolen(ST(i)), "transaction") == 0) {
+ i++;
+ if (sv_isobject(ST(i)) && (SvTYPE(SvRV(ST(i))) == SVt_PVMG)) {
+ ts = (rpmts)SvIV((SV*)SvRV(ST(i)));
+ ts = rpmtsLink(ts, bless_spec);
+ } else {
+ croak( "transaction is not a blessed SV reference" );
+ XSRETURN_UNDEF;
+ }
+ } else if (strcmp(SvPV_nolen(ST(i)), "force") == 0) {
+ i++;
+ force = ST(i);
+ } else if (strcmp(SvPV_nolen(ST(i)), "anyarch") == 0) {
+ i++;
+ anyarch = ST(i);
+ } else if (strcmp(SvPV_nolen(ST(i)), "passphrase") == 0) {
+ i++;
+ passphrase = ST(i);
+ } else if (strcmp(SvPV_nolen(ST(i)), "root") == 0) {
+ i++;
+ rootdir = ST(i);
+ } else {
+ warn("Unknown value in " bless_spec "->new, ignored");
+ i++;
+ }
+ }
+ if (!ts)
+ ts = rpmtsCreate();
+ PUTBACK;
+ _newspec(ts, specfile, passphrase, rootdir, cookies, anyarch, force);
+ SPAGAIN;
+ ts = rpmtsFree(ts);
+
+void
+Spec_DESTROY(spec)
+ Spec spec
+ CODE:
+#ifdef HDRPMMEM
+ PRINTF_FREE(bless_spec, spec, -1);
+#endif
+ freeSpec(spec);
+
+void
+Spec_srcheader(spec)
+ Spec spec
+ PPCODE:
+ if ( ! spec->sourceHeader)
+ initSourceHeader(spec);
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)headerLink(spec->sourceHeader))));
+
+void
+Spec_binheader(spec)
+ Spec spec
+ PREINIT:
+ Package pkg;
+ PPCODE:
+ for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_header, (void *)headerLink(pkg->header))));
+
+void
+Spec_srcrpm(spec)
+ Spec spec
+ PREINIT:
+ const char *name, *version, *release;
+ PPCODE:
+ (void) headerNVR(spec->packages->header, &name, &version, &release);
+ XPUSHs(sv_2mortal(newSVpvf("%s/%s-%s-%s.%ssrc.rpm",
+ rpmGetPath("%{_srcrpmdir}", NULL),
+ name, version, release,
+ spec->noSource ? "no" : ""
+ )));
+ headerFreeTag(spec->packages->header, name, RPM_STRING_TYPE);
+ headerFreeTag(spec->packages->header, version, RPM_STRING_TYPE);
+ headerFreeTag(spec->packages->header, release, RPM_STRING_TYPE);
+
+void
+Spec_binrpm(spec)
+ Spec spec
+ PREINIT:
+ Package pkg;
+ const char * binFormat;
+ char * binRpm;
+ PPCODE:
+ for(pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
+ if (pkg->fileList == NULL)
+ continue;
+ /* headerCopyTags(h, pkg->header, copyTags); */
+ binFormat = rpmGetPath("%{_rpmfilename}", NULL);
+ binRpm = headerSprintf(pkg->header, binFormat, rpmTagTable,
+ rpmHeaderFormats, NULL);
+ _free(binFormat);
+ XPUSHs(sv_2mortal(newSVpv(rpmGetPath("%{_rpmdir}/", binRpm, NULL), 0)));
+ _free(binRpm);
+ }
+
+void
+Spec_check(spec, ts = NULL)
+ Spec spec
+ PREINIT:
+ int rc;
+ rpmts ts = rpmtsCreate();
+ rpmps ps;
+ PPCODE:
+ PUTBACK;
+ if (ts)
+ ts = rpmtsLink(ts, "Spec_check");
+ else
+ ts = rpmtsCreate();
+
+ if ( ! spec->sourceHeader)
+ initSourceHeader(spec);
+
+ if (!headerIsEntry(spec->sourceHeader, RPMTAG_REQUIRENAME)
+ && !headerIsEntry(spec->sourceHeader, RPMTAG_CONFLICTNAME))
+ /* XSRETURN_UNDEF; */
+ return;
+
+ (void) rpmtsAddInstallElement(ts, spec->sourceHeader, NULL, 0, NULL);
+
+ if(rpmtsCheck(ts))
+ croak("Can't check rpmts"); /* any better idea ? */
+
+ ps = rpmtsProblems(ts);
+ if (ps && ps->numProblems) /* if no problem, return undef */
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmps, ps)));
+ ts = rpmtsFree(ts);
+ SPAGAIN;
+
+
+int
+Spec_build(spec, sv_buildflags)
+ Spec spec
+ SV * sv_buildflags
+ PREINIT:
+ rpmts ts = rpmtsCreate();
+ CODE:
+ RETVAL = _specbuild(ts, spec, sv_buildflags);
+ ts = rpmtsFree(ts);
+ OUTPUT:
+ RETVAL
+
+const char *
+Spec_specfile(spec)
+ Spec spec
+ CODE:
+ RETVAL = spec->specFile;
+ OUTPUT:
+ RETVAL
+
+void
+Spec_sources(spec, is = 0)
+ Spec spec
+ int is
+ PREINIT:
+ struct Source *srcPtr;
+ PPCODE:
+ for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
+ char * dest = NULL;
+ int len;
+ if (is && !(srcPtr->flags & is))
+ continue;
+ len = strlen(srcPtr->source);
+ dest = malloc(len);
+ memcpy(dest, srcPtr->source, len);
+ XPUSHs(sv_2mortal(newSVpv(dest, len)));
+ }
+
+void
+Spec_sources_url(spec, is = 0)
+ Spec spec
+ int is
+ PREINIT:
+ struct Source * srcPtr;
+ PPCODE:
+ for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
+ char * dest = NULL;
+ int len;
+ if (is && !(srcPtr->flags & is))
+ continue;
+ len = strlen(srcPtr->fullSource);
+ dest = malloc(len);
+ memcpy(dest, srcPtr->fullSource, len);
+ XPUSHs(sv_2mortal(newSVpv(dest, len)));
+ }
+
+
+MODULE = RPM4 PACKAGE = RPM4::Db::_Problems PREFIX = ps_
+
+void
+ps_new(perlclass, ts)
+ char * perlclass
+ rpmts ts
+ PREINIT:
+ rpmps ps;
+ PPCODE:
+ ps = rpmtsProblems(ts);
+ if (ps && ps->numProblems) /* if no problem, return undef */
+ XPUSHs(sv_2mortal(sv_setref_pv(newSVpv("", 0), bless_rpmps, ps)));
+
+void
+ps_DESTROY(ps)
+ rpmps ps
+ PPCODE:
+ ps = rpmpsFree(ps);
+
+int
+ps_count(ps)
+ rpmps ps
+ CODE:
+ RETVAL = rpmpsNumProblems(ps);
+ OUTPUT:
+ RETVAL
+
+void
+ps_print(ps, fp)
+ rpmps ps
+ FILE *fp
+ PPCODE:
+ rpmpsPrint(fp, ps);
+
+int
+ps_isignore(ps, numpb)
+ rpmps ps
+ int numpb
+ PREINIT:
+ rpmProblem p;
+ CODE:
+ if (ps->numProblems < numpb)
+ RETVAL = 0; /* croak here ? */
+ else {
+ p = ps->probs + numpb;
+ RETVAL = p->ignoreProblem;
+ }
+ OUTPUT:
+ RETVAL
+
+const char *
+ps_fmtpb(ps, numpb)
+ rpmps ps
+ int numpb
+ PREINIT:
+ rpmProblem p;
+ CODE:
+ if (ps->numProblems < numpb)
+ RETVAL = NULL;
+ else {
+ p = ps->probs + numpb;
+ RETVAL = rpmProblemString(p);
+ }
+ OUTPUT:
+ RETVAL
+
diff --git a/RPM4/src/RPM4sign.c b/RPM4/src/RPM4sign.c
new file mode 100644
index 0000000..04bb60f
--- /dev/null
+++ b/RPM4/src/RPM4sign.c
@@ -0,0 +1,28 @@
+/* $Id$ */
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#undef Fflush
+#undef Mkdir
+#undef Stat
+
+#include <rpm/rpmcli.h>
+
+#include "RPM4.h"
+
+/* Hight level function */
+int rpmsign(char *passphrase, const char *rpm) {
+ QVA_t qva = &rpmQVKArgs;
+ const char * file[2];
+
+ file[0] = rpm;
+ file[1] = NULL;
+
+ qva->qva_mode = RPMSIGN_ADD_SIGNATURE;
+ qva->passPhrase = passphrase;
+
+ return rpmcliSign(NULL, qva, file);
+}
+
diff --git a/RPM4/src/typemap b/RPM4/src/typemap
new file mode 100644
index 0000000..1889a0a
--- /dev/null
+++ b/RPM4/src/typemap
@@ -0,0 +1,21 @@
+TYPEMAP
+Header O_OBJECT
+Spec O_OBJECT
+rpmts O_OBJECT
+rpmds O_OBJECT
+rpmfi O_OBJECT
+rpmte O_OBJECT
+rpmps O_OBJECT
+
+INPUT
+O_OBJECT
+ if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG))
+ $var = ($type)SvIV((SV*)SvRV( $arg ));
+ else {
+ warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
+ XSRETURN_UNDEF;
+ }
+
+OUTPUT
+O_OBJECT
+ sv_setref_pv( $arg, (char *)CLASS, (void*)$var );