diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-12 15:17:20 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-12 15:17:20 +0900 |
commit | 7df2385c2f6c93f96e00bc87f2086066cae89ecc (patch) | |
tree | 79d5c20a494622eb084de831a2a51530cd421e33 /python | |
parent | b7a3bffb8e0341b7e4ef69def268bca3a7f279ff (diff) | |
download | rpm-tizen_2.1.tar.gz rpm-tizen_2.1.tar.bz2 rpm-tizen_2.1.zip |
Tizen 2.1 basesubmit/tizen_2.2/20130710.072219submit/tizen_2.1/20130423.104200accepted/tizen_2.1/20130423.1513382.2_release2.2.1_release2.1b_releasetizen_2.2tizen_2.1
Diffstat (limited to 'python')
34 files changed, 6474 insertions, 0 deletions
diff --git a/python/Makefile.am b/python/Makefile.am new file mode 100644 index 0000000..4f85519 --- /dev/null +++ b/python/Makefile.am @@ -0,0 +1,51 @@ +# Makefile for rpm library. + +EXTRA_DIST = rpm/__init__.py rpm/transaction.py + +AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include/ +AM_CPPFLAGS += -I$(top_srcdir)/python +AM_CPPFLAGS += -I$(top_srcdir)/misc +AM_CPPFLAGS += -I@WITH_PYTHON_INCLUDE@ + +pkgpyexec_LTLIBRARIES = _rpmmodule.la _rpmbmodule.la _rpmsmodule.la +pkgpyexec_DATA = rpm/__init__.py rpm/transaction.py + +_rpmmodule_la_LDFLAGS = -module -avoid-version -shared +_rpmmodule_la_LIBADD = \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la \ + @WITH_PYTHON_LIB@ + +_rpmmodule_la_SOURCES = rpmmodule.c rpmsystem-py.h \ + header-py.c header-py.h \ + rpmds-py.c rpmds-py.h \ + rpmfd-py.c rpmfd-py.h \ + rpmfi-py.c rpmfi-py.h \ + rpmkeyring-py.c rpmkeyring-py.h \ + rpmmi-py.c rpmmi-py.h \ + rpmii-py.c rpmii-py.h \ + rpmps-py.c rpmps-py.h \ + rpmmacro-py.c rpmmacro-py.h \ + rpmtd-py.c rpmtd-py.h \ + rpmte-py.c rpmte-py.h \ + rpmts-py.c rpmts-py.h + +_rpmbmodule_la_LDFLAGS = -module -avoid-version -shared +_rpmbmodule_la_LIBADD = \ + $(top_builddir)/build/librpmbuild.la \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la \ + @WITH_PYTHON_LIB@ + +_rpmbmodule_la_SOURCES = rpmbmodule.c rpmsystem-py.h \ + spec-py.c spec-py.h + +_rpmsmodule_la_LDFLAGS = -module -avoid-version -shared +_rpmsmodule_la_LIBADD = \ + $(top_builddir)/sign/librpmsign.la \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la \ + @WITH_PYTHON_LIB@ + +_rpmsmodule_la_SOURCES = rpmsmodule.c rpmsystem-py.h + diff --git a/python/Makefile.in b/python/Makefile.in new file mode 100644 index 0000000..1c97893 --- /dev/null +++ b/python/Makefile.in @@ -0,0 +1,742 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for rpm library. + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = python +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(pkgpyexecdir)" \ + "$(DESTDIR)$(pkgpyexecdir)" +LTLIBRARIES = $(pkgpyexec_LTLIBRARIES) +_rpmbmodule_la_DEPENDENCIES = $(top_builddir)/build/librpmbuild.la \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la +am__rpmbmodule_la_OBJECTS = rpmbmodule.lo spec-py.lo +_rpmbmodule_la_OBJECTS = $(am__rpmbmodule_la_OBJECTS) +_rpmbmodule_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(_rpmbmodule_la_LDFLAGS) $(LDFLAGS) -o $@ +_rpmmodule_la_DEPENDENCIES = $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la +am__rpmmodule_la_OBJECTS = rpmmodule.lo header-py.lo rpmds-py.lo \ + rpmfd-py.lo rpmfi-py.lo rpmkeyring-py.lo rpmmi-py.lo \ + rpmii-py.lo rpmps-py.lo rpmmacro-py.lo rpmtd-py.lo rpmte-py.lo \ + rpmts-py.lo +_rpmmodule_la_OBJECTS = $(am__rpmmodule_la_OBJECTS) +_rpmmodule_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(_rpmmodule_la_LDFLAGS) $(LDFLAGS) -o $@ +_rpmsmodule_la_DEPENDENCIES = $(top_builddir)/sign/librpmsign.la \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la +am__rpmsmodule_la_OBJECTS = rpmsmodule.lo +_rpmsmodule_la_OBJECTS = $(am__rpmsmodule_la_OBJECTS) +_rpmsmodule_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(_rpmsmodule_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(_rpmbmodule_la_SOURCES) $(_rpmmodule_la_SOURCES) \ + $(_rpmsmodule_la_SOURCES) +DIST_SOURCES = $(_rpmbmodule_la_SOURCES) $(_rpmmodule_la_SOURCES) \ + $(_rpmsmodule_la_SOURCES) +DATA = $(pkgpyexec_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOM4TE = @AUTOM4TE@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FIXPERMS = @FIXPERMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RPMCANONARCH = @RPMCANONARCH@ +RPMCANONCOLOR = @RPMCANONCOLOR@ +RPMCANONGNU = @RPMCANONGNU@ +RPMCANONOS = @RPMCANONOS@ +RPMCANONVENDOR = @RPMCANONVENDOR@ +RPMCONFIGDIR = @RPMCONFIGDIR@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WITH_ACL_LIB = @WITH_ACL_LIB@ +WITH_BZ2_LIB = @WITH_BZ2_LIB@ +WITH_CAP_LIB = @WITH_CAP_LIB@ +WITH_DB_LIB = @WITH_DB_LIB@ +WITH_LIBELF_LIB = @WITH_LIBELF_LIB@ +WITH_LZMA_LIB = @WITH_LZMA_LIB@ +WITH_MAGIC_INCLUDE = @WITH_MAGIC_INCLUDE@ +WITH_MAGIC_LIB = @WITH_MAGIC_LIB@ +WITH_NSS_INCLUDE = @WITH_NSS_INCLUDE@ +WITH_NSS_LIB = @WITH_NSS_LIB@ +WITH_POPT_INCLUDE = @WITH_POPT_INCLUDE@ +WITH_POPT_LIB = @WITH_POPT_LIB@ +WITH_PYTHON_INCLUDE = @WITH_PYTHON_INCLUDE@ +WITH_PYTHON_LIB = @WITH_PYTHON_LIB@ +WITH_SELINUX_LIB = @WITH_SELINUX_LIB@ +WITH_SEMANAGE_LIB = @WITH_SEMANAGE_LIB@ +WITH_ZLIB_INCLUDE = @WITH_ZLIB_INCLUDE@ +WITH_ZLIB_LIB = @WITH_ZLIB_LIB@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +__BZIP2 = @__BZIP2@ +__CAT = @__CAT@ +__CC = @__CC@ +__CHGRP = @__CHGRP@ +__CHMOD = @__CHMOD@ +__CHOWN = @__CHOWN@ +__CP = @__CP@ +__CPIO = @__CPIO@ +__CURL = @__CURL@ +__FAKECHROOT = @__FAKECHROOT@ +__FILE = @__FILE@ +__GPG = @__GPG@ +__GREP = @__GREP@ +__GZIP = @__GZIP@ +__ID = @__ID@ +__INSTALL = @__INSTALL@ +__LD = @__LD@ +__LRZIP = @__LRZIP@ +__LZIP = @__LZIP@ +__MAKE = @__MAKE@ +__MKDIR = @__MKDIR@ +__MKDIR_P = @__MKDIR_P@ +__MV = @__MV@ +__NM = @__NM@ +__OBJCOPY = @__OBJCOPY@ +__OBJDUMP = @__OBJDUMP@ +__PATCH = @__PATCH@ +__PERL = @__PERL@ +__PGP = @__PGP@ +__PYTHON = @__PYTHON@ +__RESTORECON = @__RESTORECON@ +__RM = @__RM@ +__RSH = @__RSH@ +__SED = @__SED@ +__SEMODULE = @__SEMODULE@ +__SSH = @__SSH@ +__STRIP = @__STRIP@ +__TAR = @__TAR@ +__UNZIP = @__UNZIP@ +__XZ = @__XZ@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dirstamp = @dirstamp@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = rpm/__init__.py rpm/transaction.py +AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) \ + -I$(top_builddir)/include/ -I$(top_srcdir)/python \ + -I$(top_srcdir)/misc -I@WITH_PYTHON_INCLUDE@ +pkgpyexec_LTLIBRARIES = _rpmmodule.la _rpmbmodule.la _rpmsmodule.la +pkgpyexec_DATA = rpm/__init__.py rpm/transaction.py +_rpmmodule_la_LDFLAGS = -module -avoid-version -shared +_rpmmodule_la_LIBADD = \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la \ + @WITH_PYTHON_LIB@ + +_rpmmodule_la_SOURCES = rpmmodule.c rpmsystem-py.h \ + header-py.c header-py.h \ + rpmds-py.c rpmds-py.h \ + rpmfd-py.c rpmfd-py.h \ + rpmfi-py.c rpmfi-py.h \ + rpmkeyring-py.c rpmkeyring-py.h \ + rpmmi-py.c rpmmi-py.h \ + rpmii-py.c rpmii-py.h \ + rpmps-py.c rpmps-py.h \ + rpmmacro-py.c rpmmacro-py.h \ + rpmtd-py.c rpmtd-py.h \ + rpmte-py.c rpmte-py.h \ + rpmts-py.c rpmts-py.h + +_rpmbmodule_la_LDFLAGS = -module -avoid-version -shared +_rpmbmodule_la_LIBADD = \ + $(top_builddir)/build/librpmbuild.la \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la \ + @WITH_PYTHON_LIB@ + +_rpmbmodule_la_SOURCES = rpmbmodule.c rpmsystem-py.h \ + spec-py.c spec-py.h + +_rpmsmodule_la_LDFLAGS = -module -avoid-version -shared +_rpmsmodule_la_LIBADD = \ + $(top_builddir)/sign/librpmsign.la \ + $(top_builddir)/lib/librpm.la \ + $(top_builddir)/rpmio/librpmio.la \ + @WITH_PYTHON_LIB@ + +_rpmsmodule_la_SOURCES = rpmsmodule.c rpmsystem-py.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign python/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-pkgpyexecLTLIBRARIES: $(pkgpyexec_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(pkgpyexecdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgpyexecdir)" + @list='$(pkgpyexec_LTLIBRARIES)'; test -n "$(pkgpyexecdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgpyexecdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgpyexecdir)"; \ + } + +uninstall-pkgpyexecLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkgpyexec_LTLIBRARIES)'; test -n "$(pkgpyexecdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgpyexecdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgpyexecdir)/$$f"; \ + done + +clean-pkgpyexecLTLIBRARIES: + -test -z "$(pkgpyexec_LTLIBRARIES)" || rm -f $(pkgpyexec_LTLIBRARIES) + @list='$(pkgpyexec_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +_rpmbmodule.la: $(_rpmbmodule_la_OBJECTS) $(_rpmbmodule_la_DEPENDENCIES) + $(_rpmbmodule_la_LINK) -rpath $(pkgpyexecdir) $(_rpmbmodule_la_OBJECTS) $(_rpmbmodule_la_LIBADD) $(LIBS) +_rpmmodule.la: $(_rpmmodule_la_OBJECTS) $(_rpmmodule_la_DEPENDENCIES) + $(_rpmmodule_la_LINK) -rpath $(pkgpyexecdir) $(_rpmmodule_la_OBJECTS) $(_rpmmodule_la_LIBADD) $(LIBS) +_rpmsmodule.la: $(_rpmsmodule_la_OBJECTS) $(_rpmsmodule_la_DEPENDENCIES) + $(_rpmsmodule_la_LINK) -rpath $(pkgpyexecdir) $(_rpmsmodule_la_OBJECTS) $(_rpmsmodule_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmbmodule.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmds-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmfd-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmfi-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmii-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmkeyring-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmmacro-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmmi-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmmodule.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmps-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmsmodule.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmtd-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmte-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmts-py.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spec-py.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgpyexecDATA: $(pkgpyexec_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgpyexecdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgpyexecdir)" + @list='$(pkgpyexec_DATA)'; test -n "$(pkgpyexecdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgpyexecdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgpyexecdir)" || exit $$?; \ + done + +uninstall-pkgpyexecDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgpyexec_DATA)'; test -n "$(pkgpyexecdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgpyexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgpyexecdir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkgpyexecdir)" "$(DESTDIR)$(pkgpyexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkgpyexecLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkgpyexecDATA install-pkgpyexecLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkgpyexecDATA uninstall-pkgpyexecLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkgpyexecLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgpyexecDATA \ + install-pkgpyexecLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pkgpyexecDATA uninstall-pkgpyexecLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/python/header-py.c b/python/header-py.c new file mode 100644 index 0000000..a790099 --- /dev/null +++ b/python/header-py.c @@ -0,0 +1,855 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmlib.h> /* rpmvercmp */ +#include <rpm/rpmtag.h> +#include <rpm/rpmstring.h> +#include <rpm/rpmts.h> /* XXX rpmtsCreate/rpmtsFree */ + +#include "header-py.h" +#include "rpmds-py.h" +#include "rpmfd-py.h" +#include "rpmfi-py.h" +#include "rpmtd-py.h" + +#include "debug.h" + +/** \ingroup python + * \class Rpm + * \brief START HERE / RPM base module for the Python API + * + * The rpm base module provides the main starting point for + * accessing RPM from Python. For most usage, call + * the TransactionSet method to get a transaction set (rpmts). + * + * For example: + * \code + * import rpm + * + * ts = rpm.TransactionSet() + * \endcode + * + * The transaction set will open the RPM database as needed, so + * in most cases, you do not need to explicitly open the + * database. The transaction set is the workhorse of RPM. + * + * You can open another RPM database, such as one that holds + * all packages for a given Linux distribution, to provide + * packages used to solve dependencies. To do this, use + * the following code: + * + * \code + * rpm.addMacro('_dbpath', '/path/to/alternate/database') + * solvets = rpm.TransactionSet() + * solvets.openDB() + * rpm.delMacro('_dbpath') + * + * # Open default database + * ts = rpm.TransactionSet() + * \endcode + * + * This code gives you access to two RPM databases through + * two transaction sets (rpmts): ts is a transaction set + * associated with the default RPM database and solvets + * is a transaction set tied to an alternate database, which + * is very useful for resolving dependencies. + * + * The rpm methods used here are: + * + * - addMacro(macro, value) + * @param macro Name of macro to add + * @param value Value for the macro + * + * - delMacro(macro) + * @param macro Name of macro to delete + * + */ + +/** \ingroup python + * \class Rpmhdr + * \brief A python header object represents an RPM package header. + * + * All RPM packages have headers that provide metadata for the package. + * Header objects can be returned by database queries or loaded from a + * binary package on disk. + * + * The ts.hdrFromFdno() function returns the package header from a + * package on disk, verifying package signatures and digests of the + * package while reading. + * + * Note: The older method rpm.headerFromPackage() which has been replaced + * by ts.hdrFromFdno() used to return a (hdr, isSource) tuple. + * + * If you need to distinguish source/binary headers, do: + * \code + * import os, rpm + * + * ts = rpm.TransactionSet() + * fdno = os.open("/tmp/foo-1.0-1.i386.rpm", os.O_RDONLY) + * hdr = ts.hdrFromFdno(fdno) + * os.close(fdno) + * if hdr[rpm.RPMTAG_SOURCEPACKAGE]: + * print "header is from a source package" + * else: + * print "header is from a binary package" + * \endcode + * + * The Python interface to the header data is quite elegant. It + * presents the data in a dictionary form. We'll take the header we + * just loaded and access the data within it: + * \code + * print hdr[rpm.RPMTAG_NAME] + * print hdr[rpm.RPMTAG_VERSION] + * print hdr[rpm.RPMTAG_RELEASE] + * \endcode + * in the case of our "foo-1.0-1.i386.rpm" package, this code would + * output: +\verbatim + foo + 1.0 + 1 +\endverbatim + * + * You make also access the header data by string name: + * \code + * print hdr['name'] + * print hdr['version'] + * print hdr['release'] + * \endcode + * + * This method of access is a teensy bit slower because the name must be + * translated into the tag number dynamically. You also must make sure + * the strings in header lookups don't get translated, or the lookups + * will fail. + */ + +/** \ingroup python + * \name Class: rpm.hdr + */ + +struct hdrObject_s { + PyObject_HEAD + Header h; + HeaderIterator hi; +}; + +static PyObject * hdrKeyList(hdrObject * s) +{ + PyObject * keys = PyList_New(0); + HeaderIterator hi = headerInitIterator(s->h); + rpmTagVal tag; + + while ((tag = headerNextTag(hi)) != RPMTAG_NOT_FOUND) { + PyObject *to = PyInt_FromLong(tag); + PyList_Append(keys, to); + Py_DECREF(to); + } + headerFreeIterator(hi); + + return keys; +} + +static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords) +{ + char * buf; + PyObject * rc; + int len, legacy = 0; + Header h; + static char *kwlist[] = { "legacyHeader", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy)) + return NULL; + + h = headerLink(s->h); + /* XXX this legacy switch is a hack, needs to be removed. */ + if (legacy) { + h = headerCopy(s->h); /* XXX strip region tags, etc */ + headerFree(s->h); + } + len = headerSizeof(h, HEADER_MAGIC_NO); + buf = headerUnload(h); + h = headerFree(h); + + if (buf == NULL || len == 0) { + PyErr_SetString(pyrpmError, "can't unload bad header\n"); + return NULL; + } + + rc = PyBytes_FromStringAndSize(buf, len); + buf = _free(buf); + + return rc; +} + +static PyObject * hdrExpandFilelist(hdrObject * s) +{ + DEPRECATED_METHOD("use hdr.convert() instead"); + headerConvert(s->h, HEADERCONV_EXPANDFILELIST); + + Py_RETURN_NONE; +} + +static PyObject * hdrCompressFilelist(hdrObject * s) +{ + DEPRECATED_METHOD("use hdr.convert() instead"); + headerConvert(s->h, HEADERCONV_COMPRESSFILELIST); + + Py_RETURN_NONE; +} + +/* make a header with _all_ the tags we need */ +static PyObject * hdrFullFilelist(hdrObject * s) +{ + rpmtd fileNames = rpmtdNew(); + Header h = s->h; + + DEPRECATED_METHOD("obsolete method"); + if (!headerIsEntry (h, RPMTAG_BASENAMES) + || !headerIsEntry (h, RPMTAG_DIRNAMES) + || !headerIsEntry (h, RPMTAG_DIRINDEXES)) + headerConvert(h, HEADERCONV_COMPRESSFILELIST); + + if (headerGet(h, RPMTAG_FILENAMES, fileNames, HEADERGET_EXT)) { + rpmtdSetTag(fileNames, RPMTAG_OLDFILENAMES); + headerPut(h, fileNames, HEADERPUT_DEFAULT); + rpmtdFreeData(fileNames); + } + rpmtdFree(fileNames); + + Py_RETURN_NONE; +} + +static PyObject * hdrFormat(hdrObject * s, PyObject * args, PyObject * kwds) +{ + char * fmt; + char * r; + errmsg_t err; + PyObject * result; + char * kwlist[] = {"format", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &fmt)) + return NULL; + + r = headerFormat(s->h, fmt, &err); + if (!r) { + PyErr_SetString(pyrpmError, err); + return NULL; + } + + result = Py_BuildValue("s", r); + r = _free(r); + + return result; +} + +static PyObject *hdrIsSource(hdrObject *s) +{ + return PyBool_FromLong(headerIsSource(s->h)); +} + +static int hdrContains(hdrObject *s, PyObject *pytag) +{ + rpmTagVal tag; + if (!tagNumFromPyObject(pytag, &tag)) return -1; + + return headerIsEntry(s->h, tag); +} + +static PyObject *hdrConvert(hdrObject *self, PyObject *args, PyObject *kwds) +{ + char *kwlist[] = {"op", NULL}; + int op = -1; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &op)) { + return NULL; + } + return PyBool_FromLong(headerConvert(self->h, op)); +} + +static PyObject * hdrWrite(hdrObject *s, PyObject *args, PyObject *kwds) +{ + char *kwlist[] = { "file", "magic", NULL }; + int magic = HEADER_MAGIC_YES; + rpmfdObject *fdo = NULL; + int rc; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist, + rpmfdFromPyObject, &fdo, &magic)) + return NULL; + + Py_BEGIN_ALLOW_THREADS; + rc = headerWrite(rpmfdGetFd(fdo), s->h, + magic ? HEADER_MAGIC_YES : HEADER_MAGIC_NO); + Py_END_ALLOW_THREADS; + + if (rc) PyErr_SetFromErrno(PyExc_IOError); + Py_XDECREF(fdo); /* avoid messing up errno with file close */ + if (rc) return NULL; + + Py_RETURN_NONE; +} + +/* + * Just a backwards-compatibility dummy, the arguments are not looked at + * or used. TODO: push this over to python side... + */ +static PyObject * hdr_fiFromHeader(PyObject * s, PyObject * args, PyObject * kwds) +{ + return PyObject_Call((PyObject *) &rpmfi_Type, + Py_BuildValue("(O)", s), NULL); +} + +/* Backwards compatibility. Flags argument is just a dummy and discarded. */ +static PyObject * hdr_dsFromHeader(PyObject * s, PyObject * args, PyObject * kwds) +{ + rpmTagVal tag = RPMTAG_REQUIRENAME; + rpmsenseFlags flags = 0; + char * kwlist[] = {"to", "flags", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&i:dsFromHeader", kwlist, + tagNumFromPyObject, &tag, &flags)) + return NULL; + + return PyObject_Call((PyObject *) &rpmds_Type, + Py_BuildValue("(Oi)", s, tag), NULL); +} + +static PyObject * hdr_dsOfHeader(PyObject * s) +{ + return PyObject_Call((PyObject *) &rpmds_Type, + Py_BuildValue("(Oi)", s, RPMTAG_NEVR), NULL); +} + +static long hdr_hash(PyObject * h) +{ + return (long) h; +} + +static struct PyMethodDef hdr_methods[] = { + {"keys", (PyCFunction) hdrKeyList, METH_NOARGS, + NULL }, + {"unload", (PyCFunction) hdrUnload, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"expandFilelist", (PyCFunction) hdrExpandFilelist,METH_NOARGS, + NULL }, + {"compressFilelist",(PyCFunction) hdrCompressFilelist,METH_NOARGS, + NULL }, + {"fullFilelist", (PyCFunction) hdrFullFilelist, METH_NOARGS, + NULL }, + {"convert", (PyCFunction) hdrConvert, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"format", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"sprintf", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"isSource", (PyCFunction)hdrIsSource, METH_NOARGS, + NULL }, + {"write", (PyCFunction)hdrWrite, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"dsOfHeader", (PyCFunction)hdr_dsOfHeader, METH_NOARGS, + NULL}, + {"dsFromHeader", (PyCFunction)hdr_dsFromHeader, METH_VARARGS|METH_KEYWORDS, + NULL}, + {"fiFromHeader", (PyCFunction)hdr_fiFromHeader, METH_VARARGS|METH_KEYWORDS, + NULL}, + + {NULL, NULL} /* sentinel */ +}; + +/* TODO: permit keyring check + retrofits on copy/load */ +static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) +{ + PyObject *obj = NULL; + rpmfdObject *fdo = NULL; + Header h = NULL; + char *kwlist[] = { "obj", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &obj)) { + return NULL; + } + + if (obj == NULL) { + h = headerNew(); + } else if (PyCObject_Check(obj)) { + h = PyCObject_AsVoidPtr(obj); + } else if (hdrObject_Check(obj)) { + h = headerCopy(((hdrObject*) obj)->h); + } else if (PyBytes_Check(obj)) { + h = headerCopyLoad(PyBytes_AsString(obj)); + } else if (rpmfdFromPyObject(obj, &fdo)) { + Py_BEGIN_ALLOW_THREADS; + h = headerRead(rpmfdGetFd(fdo), HEADER_MAGIC_YES); + Py_END_ALLOW_THREADS; + Py_XDECREF(fdo); + } else { + PyErr_SetString(PyExc_TypeError, "header, blob or file expected"); + return NULL; + } + + if (h == NULL) { + PyErr_SetString(pyrpmError, "bad header"); + return NULL; + } + + return hdr_Wrap(subtype, h); +} + +static void hdr_dealloc(hdrObject * s) +{ + if (s->h) headerFree(s->h); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static PyObject * hdr_iternext(hdrObject *s) +{ + PyObject *res = NULL; + rpmTagVal tag; + + if (s->hi == NULL) s->hi = headerInitIterator(s->h); + + if ((tag = headerNextTag(s->hi)) != RPMTAG_NOT_FOUND) { + res = PyInt_FromLong(tag); + } else { + s->hi = headerFreeIterator(s->hi); + } + return res; +} + +int utf8FromPyObject(PyObject *item, PyObject **str) +{ + PyObject *res = NULL; + if (PyBytes_Check(item)) { + Py_XINCREF(item); + res = item; + } else if (PyUnicode_Check(item)) { + res = PyUnicode_AsUTF8String(item); + } + if (res == NULL) return 0; + + *str = res; + return 1; +} + +int tagNumFromPyObject (PyObject *item, rpmTagVal *tagp) +{ + rpmTagVal tag = RPMTAG_NOT_FOUND; + PyObject *str = NULL; + + if (PyInt_Check(item)) { + /* XXX we should probably validate tag numbers too */ + tag = PyInt_AsLong(item); + } else if (utf8FromPyObject(item, &str)) { + tag = rpmTagGetValue(PyBytes_AsString(str)); + Py_DECREF(str); + } else { + PyErr_SetString(PyExc_TypeError, "expected a string or integer"); + return 0; + } + if (tag == RPMTAG_NOT_FOUND) { + PyErr_SetString(PyExc_ValueError, "unknown header tag"); + return 0; + } + + *tagp = tag; + return 1; +} + +static PyObject * hdrGetTag(Header h, rpmTagVal tag) +{ + PyObject *res = NULL; + struct rpmtd_s td; + + /* rpmtd_AsPyObj() knows how to handle empty containers and all */ + (void) headerGet(h, tag, &td, HEADERGET_EXT); + res = rpmtd_AsPyobj(&td); + rpmtdFreeData(&td); + return res; +} + +static int validItem(rpmTagClass tclass, PyObject *item) +{ + int rc; + + switch (tclass) { + case RPM_NUMERIC_CLASS: + rc = (PyLong_Check(item) || PyInt_Check(item)); + break; + case RPM_STRING_CLASS: + rc = (PyBytes_Check(item) || PyUnicode_Check(item)); + break; + case RPM_BINARY_CLASS: + rc = PyBytes_Check(item); + break; + default: + rc = 0; + break; + } + return rc; +} + +static int validData(rpmTagVal tag, rpmTagType type, rpmTagReturnType retype, PyObject *value) +{ + rpmTagClass tclass = rpmTagGetClass(tag); + int valid = 1; + + if (retype == RPM_SCALAR_RETURN_TYPE) { + valid = validItem(tclass, value); + } else if (retype == RPM_ARRAY_RETURN_TYPE && PyList_Check(value)) { + /* python lists can contain arbitrary objects, validate each item */ + Py_ssize_t len = PyList_Size(value); + for (Py_ssize_t i = 0; i < len; i++) { + PyObject *item = PyList_GetItem(value, i); + if (!validItem(tclass, item)) { + valid = 0; + break; + } + } + } else { + valid = 0; + } + return valid; +} + +static int hdrAppendItem(Header h, rpmTagVal tag, rpmTagType type, PyObject *item) +{ + int rc = 0; + + switch (type) { + case RPM_I18NSTRING_TYPE: /* XXX this needs to be handled separately */ + case RPM_STRING_TYPE: + case RPM_STRING_ARRAY_TYPE: { + PyObject *str = NULL; + if (utf8FromPyObject(item, &str)) + rc = headerPutString(h, tag, PyBytes_AsString(str)); + Py_XDECREF(str); + } break; + case RPM_BIN_TYPE: { + uint8_t *val = (uint8_t *) PyBytes_AsString(item); + rpm_count_t len = PyBytes_Size(item); + rc = headerPutBin(h, tag, val, len); + } break; + case RPM_INT64_TYPE: { + uint64_t val = PyInt_AsUnsignedLongLongMask(item); + rc = headerPutUint64(h, tag, &val, 1); + } break; + case RPM_INT32_TYPE: { + uint32_t val = PyInt_AsUnsignedLongMask(item); + rc = headerPutUint32(h, tag, &val, 1); + } break; + case RPM_INT16_TYPE: { + uint16_t val = PyInt_AsUnsignedLongMask(item); + rc = headerPutUint16(h, tag, &val, 1); + } break; + case RPM_INT8_TYPE: + case RPM_CHAR_TYPE: { + uint8_t val = PyInt_AsUnsignedLongMask(item); + rc = headerPutUint8(h, tag, &val, 1); + } break; + default: + PyErr_SetString(PyExc_TypeError, "unhandled datatype"); + } + return rc; +} + +static int hdrPutTag(Header h, rpmTagVal tag, PyObject *value) +{ + rpmTagType type = rpmTagGetTagType(tag); + rpmTagReturnType retype = rpmTagGetReturnType(tag); + int rc = 0; + + /* XXX this isn't really right (i18n strings etc) but for now ... */ + if (headerIsEntry(h, tag)) { + PyErr_SetString(PyExc_TypeError, "tag already exists"); + return rc; + } + + /* validate all data before trying to insert */ + if (!validData(tag, type, retype, value)) { + PyErr_SetString(PyExc_TypeError, "invalid type for tag"); + return 0; + } + + if (retype == RPM_SCALAR_RETURN_TYPE) { + rc = hdrAppendItem(h, tag, type, value); + } else if (retype == RPM_ARRAY_RETURN_TYPE && PyList_Check(value)) { + Py_ssize_t len = PyList_Size(value); + for (Py_ssize_t i = 0; i < len; i++) { + PyObject *item = PyList_GetItem(value, i); + rc = hdrAppendItem(h, tag, type, item); + } + } else { + PyErr_SetString(PyExc_RuntimeError, "cant happen, right?"); + } + + return rc; +} + +static PyObject * hdr_subscript(hdrObject * s, PyObject * item) +{ + rpmTagVal tag; + + if (!tagNumFromPyObject(item, &tag)) return NULL; + return hdrGetTag(s->h, tag); +} + +static int hdr_ass_subscript(hdrObject *s, PyObject *key, PyObject *value) +{ + rpmTagVal tag; + if (!tagNumFromPyObject(key, &tag)) return -1; + + if (value == NULL) { + /* XXX should failure raise key error? */ + headerDel(s->h, tag); + } else if (!hdrPutTag(s->h, tag, value)) { + return -1; + } + return 0; +} + +static PyObject * hdr_getattro(hdrObject * s, PyObject * n) +{ + PyObject *res = PyObject_GenericGetAttr((PyObject *) s, n); + if (res == NULL) { + PyObject *type, *value, *traceback; + rpmTagVal tag; + + /* Save and restore original exception if it's not a valid tag either */ + PyErr_Fetch(&type, &value, &traceback); + if (tagNumFromPyObject(n, &tag)) { + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); + res = hdrGetTag(s->h, tag); + } else { + PyErr_Restore(type, value, traceback); + } + } + return res; +} + +static int hdr_setattro(PyObject * o, PyObject * n, PyObject * v) +{ + return PyObject_GenericSetAttr(o, n, v); +} + +static PyMappingMethods hdr_as_mapping = { + (lenfunc) 0, /* mp_length */ + (binaryfunc) hdr_subscript, /* mp_subscript */ + (objobjargproc)hdr_ass_subscript,/* mp_ass_subscript */ +}; + +static PySequenceMethods hdr_as_sequence = { + 0, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + 0, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + (objobjproc)hdrContains, /* sq_contains */ + 0, /* sq_inplace_concat */ + 0, /* sq_inplace_repeat */ +}; + +static char hdr_doc[] = +""; + +PyTypeObject hdr_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.hdr", /* tp_name */ + sizeof(hdrObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) hdr_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc) 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + &hdr_as_sequence, /* tp_as_sequence */ + &hdr_as_mapping, /* tp_as_mapping */ + hdr_hash, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + (getattrofunc) hdr_getattro, /* tp_getattro */ + (setattrofunc) hdr_setattro, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + hdr_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)hdr_iternext, /* tp_iternext */ + hdr_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + hdr_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * hdr_Wrap(PyTypeObject *subtype, Header h) +{ + hdrObject * hdr = (hdrObject *)subtype->tp_alloc(subtype, 0); + if (hdr == NULL) return NULL; + + hdr->h = headerLink(h); + return (PyObject *) hdr; +} + +int hdrFromPyObject(PyObject *item, Header *hptr) +{ + if (hdrObject_Check(item)) { + *hptr = ((hdrObject *) item)->h; + return 1; + } else { + PyErr_SetString(PyExc_TypeError, "header object expected"); + return 0; + } +} + +/** + * This assumes the order of list matches the order of the new headers, and + * throws an exception if that isn't true. + */ +static int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag) +{ + Header h; + HeaderIterator hi; + rpmTagVal newMatch, oldMatch; + hdrObject * hdr; + rpm_count_t count = 0; + int rc = 1; /* assume failure */ + rpmtd td = rpmtdNew(); + + Py_BEGIN_ALLOW_THREADS + h = headerRead(fd, HEADER_MAGIC_YES); + Py_END_ALLOW_THREADS + + while (h) { + if (!headerGet(h, matchTag, td, HEADERGET_MINMEM)) { + PyErr_SetString(pyrpmError, "match tag missing in new header"); + goto exit; + } + newMatch = rpmtdTag(td); + rpmtdFreeData(td); + + hdr = (hdrObject *) PyList_GetItem(list, count++); + if (!hdr) goto exit; + + if (!headerGet(hdr->h, matchTag, td, HEADERGET_MINMEM)) { + PyErr_SetString(pyrpmError, "match tag missing in new header"); + goto exit; + } + oldMatch = rpmtdTag(td); + rpmtdFreeData(td); + + if (newMatch != oldMatch) { + PyErr_SetString(pyrpmError, "match tag mismatch"); + goto exit; + } + + for (hi = headerInitIterator(h); headerNext(hi, td); rpmtdFreeData(td)) + { + /* could be dupes */ + headerDel(hdr->h, rpmtdTag(td)); + headerPut(hdr->h, td, HEADERPUT_DEFAULT); + } + + headerFreeIterator(hi); + h = headerFree(h); + + Py_BEGIN_ALLOW_THREADS + h = headerRead(fd, HEADER_MAGIC_YES); + Py_END_ALLOW_THREADS + } + rc = 0; + +exit: + rpmtdFree(td); + return rc; +} + +PyObject * +rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds) +{ + FD_t fd; + int fileno; + PyObject * list; + int rc; + int matchTag; + char * kwlist[] = {"list", "fd", "matchTag", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &list, + &fileno, &matchTag)) + return NULL; + + if (!PyList_Check(list)) { + PyErr_SetString(PyExc_TypeError, "first parameter must be a list"); + return NULL; + } + + fd = fdDup(fileno); + + rc = rpmMergeHeaders (list, fd, matchTag); + Fclose(fd); + + if (rc) { + return NULL; + } + + Py_RETURN_NONE; +} + +PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds) +{ + hdrObject * h1, * h2; + char * kwlist[] = {"version0", "version1", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type, + &h1, &hdr_Type, &h2)) + return NULL; + + return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h)); +} + +static int compare_values(const char *str1, const char *str2) +{ + if (!str1 && !str2) + return 0; + else if (str1 && !str2) + return 1; + else if (!str1 && str2) + return -1; + return rpmvercmp(str1, str2); +} + +PyObject * labelCompare (PyObject * self, PyObject * args) +{ + char *v1, *r1, *v2, *r2; + const char *e1, *e2; + int rc; + + if (!PyArg_ParseTuple(args, "(zzz)(zzz)", + &e1, &v1, &r1, &e2, &v2, &r2)) + return NULL; + + if (e1 == NULL) e1 = "0"; + if (e2 == NULL) e2 = "0"; + + rc = compare_values(e1, e2); + if (!rc) { + rc = compare_values(v1, v2); + if (!rc) + rc = compare_values(r1, r2); + } + return Py_BuildValue("i", rc); +} + diff --git a/python/header-py.h b/python/header-py.h new file mode 100644 index 0000000..1103876 --- /dev/null +++ b/python/header-py.h @@ -0,0 +1,26 @@ +#ifndef RPMPYTHON_HEADER +#define RPMPYTHON_HEADER + +#include <rpm/rpmtypes.h> + +typedef struct hdrObject_s hdrObject; + +extern PyTypeObject hdr_Type; + +#define hdrObject_Check(v) ((v)->ob_type == &hdr_Type) + +#define DEPRECATED_METHOD(_msg) \ + PyErr_WarnEx(PyExc_PendingDeprecationWarning, (_msg), 2); + +extern PyObject * pyrpmError; + +PyObject * hdr_Wrap(PyTypeObject *subtype, Header h); + +int hdrFromPyObject(PyObject *item, Header *h); +int utf8FromPyObject(PyObject *item, PyObject **str); +int tagNumFromPyObject (PyObject *item, rpmTagVal *tagp); + +PyObject * labelCompare (PyObject * self, PyObject * args); +PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds); +PyObject * rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds); +#endif diff --git a/python/rpm/__init__.py b/python/rpm/__init__.py new file mode 100644 index 0000000..d868d19 --- /dev/null +++ b/python/rpm/__init__.py @@ -0,0 +1,84 @@ +r"""RPM Module + +This module enables you to manipulate rpms and the rpm database. + +""" + +import warnings +import os +from rpm._rpm import * +from rpm.transaction import * +import rpm._rpm as _rpm +_RPMVSF_NODIGESTS = _rpm._RPMVSF_NODIGESTS +_RPMVSF_NOHEADER = _rpm._RPMVSF_NOHEADER +_RPMVSF_NOPAYLOAD = _rpm._RPMVSF_NOPAYLOAD +_RPMVSF_NOSIGNATURES = _rpm._RPMVSF_NOSIGNATURES + +__version__ = _rpm.__version__ +__version_info__ = tuple(__version__.split('.')) + +# try to import build bits but dont require it +try: + from rpm._rpmb import * +except ImportError: + pass + +# try to import signing bits but dont require it +try: + from rpm._rpms import * +except ImportError: + pass + +# backwards compatibility + give the same class both ways +ts = TransactionSet + +def headerLoad(*args, **kwds): + warnings.warn("Use rpm.hdr() instead.", DeprecationWarning, stacklevel=2) + return hdr(*args, **kwds) + +def _doHeaderListFromFD(rpm_fd, retrofit): + hlist = [] + while 1: + try: + h = hdr(rpm_fd) + if retrofit: + h.convert(HEADERCONV_RETROFIT_V3) + hlist.append(h) + except _rpm.error: + break + + return hlist + +def readHeaderListFromFD(file_desc, retrofit = True): + if not isinstance(file_desc, fd): + file_desc = fd(file_desc) + return _doHeaderListFromFD(file_desc, retrofit) + +def readHeaderListFromFile(path, retrofit = True): + f = fd(path) + hlist = _doHeaderListFromFD(f, retrofit) + f.close() + return hlist + +def readHeaderFromFD(file_desc): + if not isinstance(file_desc, fd): + file_desc = fd(file_desc) + try: + offset = file_desc.tell() + h = hdr(file_desc) + except (_rpm.error, IOError): + offset = None + h = None + + return (h, offset) + +def signalsCaught(siglist): + caught = [] + for sig in siglist: + if signalCaught(sig): + caught.append(sig) + + return caught + +def dsSingle(TagN, N, EVR = "", Flags = RPMSENSE_ANY): + return ds((N, EVR, Flags), TagN) diff --git a/python/rpm/transaction.py b/python/rpm/transaction.py new file mode 100644 index 0000000..73e4b3c --- /dev/null +++ b/python/rpm/transaction.py @@ -0,0 +1,156 @@ +#!/usr/bin/python + +import rpm +from rpm._rpm import ts as TransactionSetCore + +# TODO: migrate relevant documentation from C-side +class TransactionSet(TransactionSetCore): + _probFilter = 0 + + def _wrapSetGet(self, attr, val): + oval = getattr(self, attr) + setattr(self, attr, val) + return oval + + def setVSFlags(self, flags): + return self._wrapSetGet('_vsflags', flags) + + def getVSFlags(self): + return self._vsflags + + def setColor(self, color): + return self._wrapSetGet('_color', color) + + def setPrefColor(self, color): + return self._wrapSetGet('_prefcolor', color) + + def setFlags(self, flags): + return self._wrapSetGet('_flags', flags) + + def setProbFilter(self, ignoreSet): + return self._wrapSetGet('_probFilter', ignoreSet) + + def parseSpec(self, specfile): + import _rpmb + return _rpmb.spec(specfile) + + def getKeys(self): + keys = [] + for te in self: + keys.append(te.Key()) + # Backwards compatibility goo - WTH does this return a *tuple* ?! + if not keys: + return None + else: + return tuple(keys) + + def addInstall(self, item, key, how="u"): + if isinstance(item, basestring): + f = file(item) + header = self.hdrFromFdno(f) + f.close() + elif isinstance(item, file): + header = self.hdrFromFdno(item) + else: + header = item + + if not how in ['u', 'i']: + raise ValueError('how argument must be "u" or "i"') + upgrade = (how == "u") + + if not TransactionSetCore.addInstall(self, header, key, upgrade): + raise rpm.error("adding package to transaction failed") + + def addErase(self, item): + hdrs = [] + if isinstance(item, rpm.hdr): + hdrs = [item] + elif isinstance(item, rpm.mi): + hdrs = item + elif isinstance(item, int): + hdrs = self.dbMatch(rpm.RPMDBI_PACKAGES, item) + elif isinstance(item, basestring): + hdrs = self.dbMatch(rpm.RPMDBI_LABEL, item) + else: + raise TypeError("invalid type %s" % type(item)) + + for h in hdrs: + if not TransactionSetCore.addErase(self, h): + raise rpm.error("package not installed") + + # garbage collection should take care but just in case... + if isinstance(hdrs, rpm.mi): + del hdrs + + def run(self, callback, data): + rc = TransactionSetCore.run(self, callback, data, self._probFilter) + + # crazy backwards compatibility goo: None for ok, list of problems + # if transaction didnt complete and empty list if it completed + # with errors + if rc == 0: + return None + + res = [] + if rc > 0: + for prob in self.problems(): + item = ("%s" % prob, (prob.type, prob._str, prob._num)) + res.append(item) + return res + + def check(self, *args, **kwds): + TransactionSetCore.check(self, *args, **kwds) + + # compatibility: munge problem strings into dependency tuples of doom + res = [] + for p in self.problems(): + # is it anything we need to care about? + if p.type == rpm.RPMPROB_CONFLICT: + sense = rpm.RPMDEP_SENSE_CONFLICTS + elif p.type == rpm.RPMPROB_REQUIRES: + sense = rpm.RPMDEP_SENSE_REQUIRES + else: + continue + + # strip arch, split to name, version, release + nevr = p.altNEVR.rsplit('.', 1)[0] + n, v, r = nevr.rsplit('-', 2) + + # extract the dependency information + needs = p._str.split() + needname = needs[0] + needflags = rpm.RPMSENSE_ANY + if len(needs) == 3: + needop = needs[1] + if needop.find('<') >= 0: needflags |= rpm.RPMSENSE_LESS + if needop.find('=') >= 0: needflags |= rpm.RPMSENSE_EQUAL + if needop.find('>') >= 0: needflags |= rpm.RPMSENSE_GREATER + needver = needs[2] + else: + needver = "" + + res.append(((n, v, r),(needname,needver),needflags,sense,p.key)) + + return res + + def hdrCheck(self, blob): + res, msg = TransactionSetCore.hdrCheck(self, blob) + # generate backwards compatibly broken exceptions + if res == rpm.RPMRC_NOKEY: + raise rpm.error("public key not available") + elif res == rpm.RPMRC_NOTTRUSTED: + raise rpm.error("public key not trusted") + elif res != rpm.RPMRC_OK: + raise rpm.error(msg) + + def hdrFromFdno(self, fd): + res, h = TransactionSetCore.hdrFromFdno(self, fd) + # generate backwards compatibly broken exceptions + if res == rpm.RPMRC_NOKEY: + raise rpm.error("public key not available") + elif res == rpm.RPMRC_NOTTRUSTED: + raise rpm.error("public key not trusted") + elif res != rpm.RPMRC_OK: + raise rpm.error("error reading package header") + + return h diff --git a/python/rpmbmodule.c b/python/rpmbmodule.c new file mode 100644 index 0000000..a6a35d8 --- /dev/null +++ b/python/rpmbmodule.c @@ -0,0 +1,97 @@ +#include "rpmsystem-py.h" + +#include "spec-py.h" + +#include "debug.h" + +static char rpmb__doc__[] = +""; + +/* + Do any common preliminary work before python 2 vs python 3 module creation: +*/ +static int prepareInitModule(void) +{ + if (PyType_Ready(&spec_Type) < 0) return 0; + if (PyType_Ready(&specPkg_Type) < 0) return 0; + + return 1; +} + +static int initModule(PyObject *m) +{ + Py_INCREF(&spec_Type); + PyModule_AddObject(m, "spec", (PyObject *) &spec_Type); + Py_INCREF(&specPkg_Type); + PyModule_AddObject(m, "specPkg", (PyObject *) &specPkg_Type); + +#define REGISTER_ENUM(val) PyModule_AddIntConstant(m, #val, val) + REGISTER_ENUM(RPMBUILD_ISSOURCE); + REGISTER_ENUM(RPMBUILD_ISPATCH); + REGISTER_ENUM(RPMBUILD_ISICON); + REGISTER_ENUM(RPMBUILD_ISNO); + + REGISTER_ENUM(RPMBUILD_NONE); + REGISTER_ENUM(RPMBUILD_PREP); + REGISTER_ENUM(RPMBUILD_BUILD); + REGISTER_ENUM(RPMBUILD_INSTALL); + REGISTER_ENUM(RPMBUILD_CHECK); + REGISTER_ENUM(RPMBUILD_CLEAN); + REGISTER_ENUM(RPMBUILD_FILECHECK); + REGISTER_ENUM(RPMBUILD_PACKAGESOURCE); + REGISTER_ENUM(RPMBUILD_PACKAGEBINARY); + REGISTER_ENUM(RPMBUILD_RMSOURCE); + REGISTER_ENUM(RPMBUILD_RMBUILD); + REGISTER_ENUM(RPMBUILD_RMSPEC); + + REGISTER_ENUM(RPMBUILD_PKG_NONE); + REGISTER_ENUM(RPMBUILD_PKG_NODIRTOKENS); + + REGISTER_ENUM(RPMSPEC_NONE); + REGISTER_ENUM(RPMSPEC_ANYARCH); + REGISTER_ENUM(RPMSPEC_FORCE); + REGISTER_ENUM(RPMSPEC_NOLANG); + + return 1; +} + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_rpmb", /* m_name */ + rpmb__doc__, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; + +PyObject * PyInit__rpm(void); /* XXX eliminate gcc warning */ +PyObject * PyInit__rpm(void) +{ + PyObject *m; + + if (!prepareInitModule()) + return NULL; + m = PyModule_Create(&moduledef); + if (m == NULL || !initModule(m)) { + Py_XDECREF(m); + m = NULL; + } + return m; +} +#else +void init_rpmb(void); /* XXX eliminate gcc warning */ +void init_rpmb(void) +{ + PyObject *m; + + if (!prepareInitModule()) + return; + + m = Py_InitModule3("_rpmb", NULL, rpmb__doc__); + if (m) initModule(m); +} +#endif diff --git a/python/rpmds-py.c b/python/rpmds-py.c new file mode 100644 index 0000000..1576ec7 --- /dev/null +++ b/python/rpmds-py.c @@ -0,0 +1,405 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmtypes.h> +#include <rpm/rpmstring.h> +#include <rpm/rpmlib.h> /* rpmvercmp */ + +#include "header-py.h" +#include "rpmds-py.h" + +#include "debug.h" + +struct rpmdsObject_s { + PyObject_HEAD + PyObject *md_dict; /*!< to look like PyModuleObject */ + int active; + rpmds ds; +}; + +static PyObject * +rpmds_Count(rpmdsObject * s) +{ + DEPRECATED_METHOD("use len(ds) instead"); + return Py_BuildValue("i", PyMapping_Size((PyObject *)s)); +} + +static PyObject * +rpmds_Ix(rpmdsObject * s) +{ + return Py_BuildValue("i", rpmdsIx(s->ds)); +} + +static PyObject * +rpmds_DNEVR(rpmdsObject * s) +{ + return Py_BuildValue("s", rpmdsDNEVR(s->ds)); +} + +static PyObject * +rpmds_N(rpmdsObject * s) +{ + return Py_BuildValue("s", rpmdsN(s->ds)); +} + +static PyObject * +rpmds_EVR(rpmdsObject * s) +{ + return Py_BuildValue("s", rpmdsEVR(s->ds)); +} + +static PyObject * +rpmds_Flags(rpmdsObject * s) +{ + return Py_BuildValue("i", rpmdsFlags(s->ds)); +} + +static PyObject * +rpmds_TagN(rpmdsObject * s) +{ + return Py_BuildValue("i", rpmdsTagN(s->ds)); +} + +static PyObject * +rpmds_Color(rpmdsObject * s) +{ + return Py_BuildValue("i", rpmdsColor(s->ds)); +} + +static PyObject * +rpmds_iternext(rpmdsObject * s) +{ + PyObject * result = NULL; + + /* Reset loop indices on 1st entry. */ + if (!s->active) { + s->ds = rpmdsInit(s->ds); + s->active = 1; + } + + /* If more to do, return a (N, EVR, Flags) tuple. */ + if (rpmdsNext(s->ds) >= 0) { + result = rpmds_Wrap(Py_TYPE(s), rpmdsCurrent(s->ds)); + } else + s->active = 0; + + return result; +} + +static PyObject * +rpmds_SetNoPromote(rpmdsObject * s, PyObject * args, PyObject * kwds) +{ + int nopromote; + char * kwlist[] = {"noPromote", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetNoPromote", kwlist, + &nopromote)) + return NULL; + + return Py_BuildValue("i", rpmdsSetNoPromote(s->ds, nopromote)); +} + +static PyObject * +rpmds_Notify(rpmdsObject * s, PyObject * args, PyObject * kwds) +{ + const char * where; + int rc; + char * kwlist[] = {"location", "returnCode", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "si:Notify", kwlist, + &where, &rc)) + return NULL; + + rpmdsNotify(s->ds, where, rc); + Py_RETURN_NONE; +} + +/* XXX rpmdsFind uses bsearch on s->ds, so a sort is needed. */ +static PyObject * +rpmds_Sort(rpmdsObject * s) +{ + /* XXX sort on (N,EVR,F) here. */ + Py_RETURN_NONE; +} + +static PyObject * +rpmds_Find(rpmdsObject * s, PyObject * arg) +{ + rpmdsObject * o; + + if (!PyArg_Parse(arg, "O!:Find", &rpmds_Type, &o)) + return NULL; + + /* XXX make sure ods index is valid, real fix in lib/rpmds.c. */ + if (rpmdsIx(o->ds) == -1) rpmdsSetIx(o->ds, 0); + + return Py_BuildValue("i", rpmdsFind(s->ds, o->ds)); +} + +static PyObject * +rpmds_Merge(rpmdsObject * s, PyObject * arg) +{ + rpmdsObject * o; + + if (!PyArg_Parse(arg, "O!:Merge", &rpmds_Type, &o)) + return NULL; + + return Py_BuildValue("i", rpmdsMerge(&s->ds, o->ds)); +} +static PyObject * +rpmds_Search(rpmdsObject * s, PyObject * arg) +{ + rpmdsObject * o; + + if (!PyArg_Parse(arg, "O!:Merge", &rpmds_Type, &o)) + return NULL; + + return Py_BuildValue("i", rpmdsSearch(s->ds, o->ds)); +} + +static PyObject *rpmds_Compare(rpmdsObject * s, PyObject * o) +{ + rpmdsObject * ods; + + if (!PyArg_Parse(o, "O!:Compare", &rpmds_Type, &ods)) + return NULL; + + return PyBool_FromLong(rpmdsCompare(s->ds, ods->ds)); +} + +static PyObject *rpmds_Instance(rpmdsObject * s) +{ + return Py_BuildValue("i", rpmdsInstance(s->ds)); +} + +static PyObject * rpmds_Rpmlib(rpmdsObject * s) +{ + rpmds ds = NULL; + int xx; + + /* XXX check return code, permit arg (NULL uses system default). */ + xx = rpmdsRpmlib(&ds, NULL); + + return rpmds_Wrap(&rpmds_Type, ds); +} + +static struct PyMethodDef rpmds_methods[] = { + {"Count", (PyCFunction)rpmds_Count, METH_NOARGS, + "Deprecated, use len(ds) instead.\n" }, + {"Ix", (PyCFunction)rpmds_Ix, METH_NOARGS, + "ds.Ix -> Ix - Return current element index.\n" }, + {"DNEVR", (PyCFunction)rpmds_DNEVR, METH_NOARGS, + "ds.DNEVR -> DNEVR - Return current DNEVR.\n" }, + {"N", (PyCFunction)rpmds_N, METH_NOARGS, + "ds.N -> N - Return current N.\n" }, + {"EVR", (PyCFunction)rpmds_EVR, METH_NOARGS, + "ds.EVR -> EVR - Return current EVR.\n" }, + {"Flags", (PyCFunction)rpmds_Flags, METH_NOARGS, + "ds.Flags -> Flags - Return current Flags.\n" }, + {"TagN", (PyCFunction)rpmds_TagN, METH_NOARGS, + "ds.TagN -> TagN - Return current TagN.\n" }, + {"Color", (PyCFunction)rpmds_Color, METH_NOARGS, + "ds.Color -> Color - Return current Color.\n" }, + {"SetNoPromote",(PyCFunction)rpmds_SetNoPromote, METH_VARARGS|METH_KEYWORDS, + NULL}, + {"Notify", (PyCFunction)rpmds_Notify, METH_VARARGS|METH_KEYWORDS, + NULL}, + {"Sort", (PyCFunction)rpmds_Sort, METH_NOARGS, + NULL}, + {"Find", (PyCFunction)rpmds_Find, METH_O, + NULL}, + {"Merge", (PyCFunction)rpmds_Merge, METH_O, + NULL}, + {"Search", (PyCFunction)rpmds_Search, METH_O, +"ds.Search(element) -> matching ds index (-1 on failure)\n\ +- Check that element dependency range overlaps some member of ds.\n\ +The current index in ds is positioned at overlapping member upon success.\n" }, + {"Rpmlib", (PyCFunction)rpmds_Rpmlib, METH_NOARGS|METH_STATIC, + "ds.Rpmlib -> nds - Return internal rpmlib dependency set.\n"}, + {"Compare", (PyCFunction)rpmds_Compare, METH_O, + NULL}, + {"Instance", (PyCFunction)rpmds_Instance, METH_NOARGS, + NULL}, + {NULL, NULL} /* sentinel */ +}; + +/* ---------- */ + +static void +rpmds_dealloc(rpmdsObject * s) +{ + s->ds = rpmdsFree(s->ds); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static Py_ssize_t rpmds_length(rpmdsObject * s) +{ + return rpmdsCount(s->ds); +} + +static PyObject * +rpmds_subscript(rpmdsObject * s, PyObject * key) +{ + int ix; + + if (!PyInt_Check(key)) { + PyErr_SetString(PyExc_TypeError, "integer expected"); + return NULL; + } + + ix = (int) PyInt_AsLong(key); + rpmdsSetIx(s->ds, ix); + return Py_BuildValue("s", rpmdsDNEVR(s->ds)); +} + +static PyMappingMethods rpmds_as_mapping = { + (lenfunc) rpmds_length, /* mp_length */ + (binaryfunc) rpmds_subscript, /* mp_subscript */ + (objobjargproc)0, /* mp_ass_subscript */ +}; + +static int rpmds_init(rpmdsObject * s, PyObject *args, PyObject *kwds) +{ + s->active = 0; + return 0; +} + +static int depflags(PyObject *o, rpmsenseFlags *senseFlags) +{ + int ok = 0; + PyObject *str = NULL; + rpmsenseFlags flags = RPMSENSE_ANY; + + if (PyInt_Check(o)) { + ok = 1; + flags = PyInt_AsLong(o); + } else if (utf8FromPyObject(o, &str)) { + ok = 1; + for (const char *s = PyBytes_AsString(str); *s; s++) { + switch (*s) { + case '=': + flags |= RPMSENSE_EQUAL; + break; + case '<': + flags |= RPMSENSE_LESS; + break; + case '>': + flags |= RPMSENSE_GREATER; + break; + default: + ok = 0; + break; + } + } + Py_DECREF(str); + } + + if (flags == (RPMSENSE_EQUAL|RPMSENSE_LESS|RPMSENSE_GREATER)) + ok = 0; + + if (ok) + *senseFlags = flags; + + return ok; +} + +static PyObject * rpmds_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + rpmTagVal tagN = RPMTAG_REQUIRENAME; + rpmds ds = NULL; + Header h = NULL; + char * kwlist[] = {"obj", "tag", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:rpmds_new", kwlist, + &obj, tagNumFromPyObject, &tagN)) + return NULL; + + if (PyTuple_Check(obj)) { + const char *name = NULL; + const char *evr = NULL; + rpmsenseFlags flags = RPMSENSE_ANY; + /* TODO: if flags are specified, evr should be required too */ + if (PyArg_ParseTuple(obj, "s|O&s", &name, depflags, &flags, &evr)) { + ds = rpmdsSingle(tagN, name, evr, flags); + } else { + PyErr_SetString(PyExc_ValueError, "invalid dependency tuple"); + return NULL; + } + } else if (hdrFromPyObject(obj, &h)) { + if (tagN == RPMTAG_NEVR) { + ds = rpmdsThis(h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL); + } else { + ds = rpmdsNew(h, tagN, 0); + } + } else { + PyErr_SetString(PyExc_TypeError, "header or tuple expected"); + return NULL; + } + + return rpmds_Wrap(subtype, ds); +} + +static char rpmds_doc[] = +""; + +PyTypeObject rpmds_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.ds", /* tp_name */ + sizeof(rpmdsObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor) rpmds_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + &rpmds_as_mapping, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmds_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc) rpmds_iternext, /* tp_iternext */ + rpmds_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc) rpmds_init, /* tp_init */ + 0, /* tp_alloc */ + (newfunc) rpmds_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +/* ---------- */ + +rpmds dsFromDs(rpmdsObject * s) +{ + return s->ds; +} + +PyObject * rpmds_Wrap(PyTypeObject *subtype, rpmds ds) +{ + rpmdsObject * s = (rpmdsObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->ds = ds; + s->active = 0; + return (PyObject *) s; +} + diff --git a/python/rpmds-py.h b/python/rpmds-py.h new file mode 100644 index 0000000..ffbdef4 --- /dev/null +++ b/python/rpmds-py.h @@ -0,0 +1,16 @@ +#ifndef H_RPMDS_PY +#define H_RPMDS_PY + +#include <rpm/rpmds.h> + +typedef struct rpmdsObject_s rpmdsObject; + +extern PyTypeObject rpmds_Type; + +#define rpmdsObject_Check(v) ((v)->ob_type == &rpmds_Type) + +rpmds dsFromDs(rpmdsObject * ds); + +PyObject * rpmds_Wrap(PyTypeObject *subtype, rpmds ds); + +#endif diff --git a/python/rpmfd-py.c b/python/rpmfd-py.c new file mode 100644 index 0000000..f3536ea --- /dev/null +++ b/python/rpmfd-py.c @@ -0,0 +1,354 @@ + +#include "rpmsystem-py.h" +#include <rpm/rpmstring.h> +#include "header-py.h" /* XXX for utf8FromPyObject() only */ +#include "rpmfd-py.h" + +struct rpmfdObject_s { + PyObject_HEAD + PyObject *md_dict; + FD_t fd; +}; + +FD_t rpmfdGetFd(rpmfdObject *fdo) +{ + return fdo->fd; +} + +int rpmfdFromPyObject(PyObject *obj, rpmfdObject **fdop) +{ + rpmfdObject *fdo = NULL; + + if (rpmfdObject_Check(obj)) { + Py_INCREF(obj); + fdo = (rpmfdObject *) obj; + } else { + fdo = (rpmfdObject *) PyObject_Call((PyObject *)&rpmfd_Type, + Py_BuildValue("(O)", obj), NULL); + } + if (fdo == NULL) return 0; + + if (Ferror(fdo->fd)) { + Py_DECREF(fdo); + PyErr_SetString(PyExc_IOError, Fstrerror(fdo->fd)); + return 0; + } + *fdop = fdo; + return 1; +} + +static PyObject *err_closed(void) +{ + PyErr_SetString(PyExc_ValueError, "I/O operation on closed file"); + return NULL; +} + +static FD_t openPath(const char *path, const char *mode, const char *flags) +{ + FD_t fd; + char *m = rstrscat(NULL, mode, ".", flags, NULL); + Py_BEGIN_ALLOW_THREADS + fd = Fopen(path, m); + Py_END_ALLOW_THREADS; + free(m); + return fd; +} + +static PyObject *rpmfd_new(PyTypeObject *subtype, + PyObject *args, PyObject *kwds) +{ + char *kwlist[] = { "obj", "mode", "flags", NULL }; + char *mode = "r"; + char *flags = "ufdio"; + PyObject *fo = NULL; + rpmfdObject *s = NULL; + FD_t fd = NULL; + int fdno; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ss", kwlist, + &fo, &mode, &flags)) + return NULL; + + if (PyBytes_Check(fo)) { + fd = openPath(PyBytes_AsString(fo), mode, flags); + } else if (PyUnicode_Check(fo)) { + PyObject *enc = NULL; + int rc; +#if PY_MAJOR_VERSION >= 3 + rc = PyUnicode_FSConverter(fo, &enc); +#else + rc = utf8FromPyObject(fo, &enc); +#endif + if (rc == 0) + return NULL; + + fd = openPath(PyBytes_AsString(enc), mode, flags); + Py_DECREF(enc); + + } else if ((fdno = PyObject_AsFileDescriptor(fo)) >= 0) { + fd = fdDup(fdno); + } else { + PyErr_SetString(PyExc_TypeError, "path or file object expected"); + return NULL; + } + + if (Ferror(fd)) { + PyErr_SetString(PyExc_IOError, Fstrerror(fd)); + return NULL; + } + + if ((s = (rpmfdObject *)subtype->tp_alloc(subtype, 0)) == NULL) { + Fclose(fd); + return NULL; + } + /* TODO: remember our filename, mode & flags */ + s->fd = fd; + return (PyObject*) s; +} + +static PyObject *do_close(rpmfdObject *s) +{ + /* mimic python fileobject: close on closed file is not an error */ + if (s->fd) { + Py_BEGIN_ALLOW_THREADS + Fclose(s->fd); + Py_END_ALLOW_THREADS + s->fd = NULL; + } + Py_RETURN_NONE; +} + +static PyObject *rpmfd_close(rpmfdObject *s) +{ + return do_close(s); +} + +static void rpmfd_dealloc(rpmfdObject *s) +{ + PyObject *res = do_close(s); + Py_XDECREF(res); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static PyObject *rpmfd_fileno(rpmfdObject *s) +{ + int fno; + if (s->fd == NULL) return err_closed(); + + Py_BEGIN_ALLOW_THREADS + fno = Fileno(s->fd); + Py_END_ALLOW_THREADS + + if (Ferror(s->fd)) { + PyErr_SetString(PyExc_IOError, Fstrerror(s->fd)); + return NULL; + } + return Py_BuildValue("i", fno); +} + +static PyObject *rpmfd_flush(rpmfdObject *s) +{ + int rc; + + if (s->fd == NULL) return err_closed(); + + Py_BEGIN_ALLOW_THREADS + rc = Fflush(s->fd); + Py_END_ALLOW_THREADS + + if (rc || Ferror(s->fd)) { + PyErr_SetString(PyExc_IOError, Fstrerror(s->fd)); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject *rpmfd_isatty(rpmfdObject *s) +{ + int fileno; + if (s->fd == NULL) return err_closed(); + + Py_BEGIN_ALLOW_THREADS + fileno = Fileno(s->fd); + Py_END_ALLOW_THREADS + + if (Ferror(s->fd)) { + PyErr_SetString(PyExc_IOError, Fstrerror(s->fd)); + return NULL; + } + return PyBool_FromLong(isatty(fileno)); +} + +static PyObject *rpmfd_seek(rpmfdObject *s, PyObject *args, PyObject *kwds) +{ + char *kwlist[] = { "offset", "whence", NULL }; + off_t offset; + int whence = SEEK_SET; + int rc = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwlist, + &offset, &whence)) + return NULL; + + if (s->fd == NULL) return err_closed(); + + Py_BEGIN_ALLOW_THREADS + rc = Fseek(s->fd, offset, whence); + Py_END_ALLOW_THREADS + if (rc < 0 || Ferror(s->fd)) { + PyErr_SetString(PyExc_IOError, Fstrerror(s->fd)); + return NULL; + } + Py_RETURN_NONE; +} + +static PyObject *rpmfd_tell(rpmfdObject *s) +{ + off_t offset; + Py_BEGIN_ALLOW_THREADS + offset = Ftell(s->fd); + Py_END_ALLOW_THREADS + return Py_BuildValue("L", offset); + +} + +static PyObject *rpmfd_read(rpmfdObject *s, PyObject *args, PyObject *kwds) +{ + char *kwlist[] = { "size", NULL }; + char buf[BUFSIZ]; + ssize_t chunksize = sizeof(buf); + ssize_t left = -1; + ssize_t nb = 0; + PyObject *res = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", kwlist, &left)) + return NULL; + + if (s->fd == NULL) return err_closed(); + + /* ConcatAndDel() doesn't work on NULL string, meh */ + res = PyBytes_FromStringAndSize(NULL, 0); + do { + if (left >= 0 && left < chunksize) + chunksize = left; + + Py_BEGIN_ALLOW_THREADS + nb = Fread(buf, 1, chunksize, s->fd); + Py_END_ALLOW_THREADS + + if (nb > 0) { + PyObject *tmp = PyBytes_FromStringAndSize(buf, nb); + PyString_ConcatAndDel(&res, tmp); + left -= nb; + } + } while (nb > 0); + + if (Ferror(s->fd)) { + PyErr_SetString(PyExc_IOError, Fstrerror(s->fd)); + Py_XDECREF(res); + return NULL; + } else { + return res; + } +} + +static PyObject *rpmfd_write(rpmfdObject *s, PyObject *args, PyObject *kwds) +{ + + const char *buf = NULL; + ssize_t size = 0; + char *kwlist[] = { "buffer", NULL }; + ssize_t rc = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &buf, &size)) { + return NULL; + } + + if (s->fd == NULL) return err_closed(); + + Py_BEGIN_ALLOW_THREADS + rc = Fwrite(buf, 1, size, s->fd); + Py_END_ALLOW_THREADS + + if (Ferror(s->fd)) { + PyErr_SetString(PyExc_IOError, Fstrerror(s->fd)); + return NULL; + } + return Py_BuildValue("n", rc); +} + +static char rpmfd_doc[] = ""; + +static struct PyMethodDef rpmfd_methods[] = { + { "close", (PyCFunction) rpmfd_close, METH_NOARGS, + NULL }, + { "fileno", (PyCFunction) rpmfd_fileno, METH_NOARGS, + NULL }, + { "flush", (PyCFunction) rpmfd_flush, METH_NOARGS, + NULL }, + { "isatty", (PyCFunction) rpmfd_isatty, METH_NOARGS, + NULL }, + { "read", (PyCFunction) rpmfd_read, METH_VARARGS|METH_KEYWORDS, + NULL }, + { "seek", (PyCFunction) rpmfd_seek, METH_VARARGS|METH_KEYWORDS, + NULL }, + { "tell", (PyCFunction) rpmfd_tell, METH_NOARGS, + NULL }, + { "write", (PyCFunction) rpmfd_write, METH_VARARGS|METH_KEYWORDS, + NULL }, + { NULL, NULL } +}; + +static PyObject *rpmfd_get_closed(rpmfdObject *s) +{ + return PyBool_FromLong((s->fd == NULL)); +} + +static PyGetSetDef rpmfd_getseters[] = { + { "closed", (getter)rpmfd_get_closed, NULL, NULL }, + { NULL }, +}; + +PyTypeObject rpmfd_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.fd", /* tp_name */ + sizeof(rpmfdObject), /* tp_size */ + 0, /* tp_itemsize */ + /* methods */ + (destructor) rpmfd_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmfd_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rpmfd_methods, /* tp_methods */ + 0, /* tp_members */ + rpmfd_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)0, /* tp_init */ + (allocfunc)0, /* tp_alloc */ + (newfunc) rpmfd_new, /* tp_new */ + (freefunc)0, /* tp_free */ + 0, /* tp_is_gc */ +}; diff --git a/python/rpmfd-py.h b/python/rpmfd-py.h new file mode 100644 index 0000000..b84e174 --- /dev/null +++ b/python/rpmfd-py.h @@ -0,0 +1,17 @@ +#ifndef H_RPMFD_PY +#define H_RPMFD_PY + +#include <rpm/rpmio.h> + +typedef struct rpmfdObject_s rpmfdObject; + +extern PyTypeObject rpmfd_Type; + +#define rpmfdObject_Check(v) ((v)->ob_type == &rpmfd_Type) + +FD_t rpmfdGetFd(rpmfdObject *fdo); + +int rpmfdFromPyObject(PyObject *obj, rpmfdObject **fdop); + + +#endif diff --git a/python/rpmfi-py.c b/python/rpmfi-py.c new file mode 100644 index 0000000..52a2a3a --- /dev/null +++ b/python/rpmfi-py.c @@ -0,0 +1,378 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmtypes.h> +#include <rpm/rpmpgp.h> + +#include "header-py.h" +#include "rpmfi-py.h" + +#include "debug.h" + +struct rpmfiObject_s { + PyObject_HEAD + PyObject *md_dict; /*!< to look like PyModuleObject */ + int active; + rpmfi fi; +}; + +static PyObject * +rpmfi_FC(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFC(s->fi)); +} + +static PyObject * +rpmfi_FX(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFX(s->fi)); +} + +static PyObject * +rpmfi_DC(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiDC(s->fi)); +} + +static PyObject * +rpmfi_DX(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiDX(s->fi)); +} + +static PyObject * +rpmfi_BN(rpmfiObject * s) +{ + return Py_BuildValue("s", rpmfiBN(s->fi)); +} + +static PyObject * +rpmfi_DN(rpmfiObject * s) +{ + return Py_BuildValue("s", rpmfiDN(s->fi)); +} + +static PyObject * +rpmfi_FN(rpmfiObject * s) +{ + return Py_BuildValue("s", rpmfiFN(s->fi)); +} + +static PyObject * +rpmfi_FFlags(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFFlags(s->fi)); +} + +static PyObject * +rpmfi_VFlags(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiVFlags(s->fi)); +} + +static PyObject * +rpmfi_FMode(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFMode(s->fi)); +} + +static PyObject * +rpmfi_FState(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFState(s->fi)); +} + +/* XXX rpmfiFDigest */ +static PyObject * +rpmfi_Digest(rpmfiObject * s) +{ + char *digest = rpmfiFDigestHex(s->fi, NULL); + if (digest) { + PyObject *dig = Py_BuildValue("s", digest); + free(digest); + return dig; + } else { + Py_RETURN_NONE; + } +} + +static PyObject * +rpmfi_FLink(rpmfiObject * s) +{ + return Py_BuildValue("s", rpmfiFLink(s->fi)); +} + +static PyObject * +rpmfi_FSize(rpmfiObject * s) +{ + return Py_BuildValue("L", rpmfiFSize(s->fi)); +} + +static PyObject * +rpmfi_FRdev(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFRdev(s->fi)); +} + +static PyObject * +rpmfi_FMtime(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFMtime(s->fi)); +} + +static PyObject * +rpmfi_FUser(rpmfiObject * s) +{ + return Py_BuildValue("s", rpmfiFUser(s->fi)); +} + +static PyObject * +rpmfi_FGroup(rpmfiObject * s) +{ + return Py_BuildValue("s", rpmfiFGroup(s->fi)); +} + +static PyObject * +rpmfi_FColor(rpmfiObject * s) +{ + return Py_BuildValue("i", rpmfiFColor(s->fi)); +} + +static PyObject * +rpmfi_FClass(rpmfiObject * s) +{ + const char * FClass; + + if ((FClass = rpmfiFClass(s->fi)) == NULL) + FClass = ""; + return Py_BuildValue("s", FClass); +} + +static PyObject * +rpmfi_iternext(rpmfiObject * s) +{ + PyObject * result = NULL; + + /* Reset loop indices on 1st entry. */ + if (!s->active) { + s->fi = rpmfiInit(s->fi, 0); + s->active = 1; + } + + /* If more to do, return the file tuple. */ + if (rpmfiNext(s->fi) >= 0) { + const char * FN = rpmfiFN(s->fi); + rpm_loff_t FSize = rpmfiFSize(s->fi); + int FMode = rpmfiFMode(s->fi); + int FMtime = rpmfiFMtime(s->fi); + int FFlags = rpmfiFFlags(s->fi); + int FRdev = rpmfiFRdev(s->fi); + int FInode = rpmfiFInode(s->fi); + int FNlink = rpmfiFNlink(s->fi); + int FState = rpmfiFState(s->fi); + int VFlags = rpmfiVFlags(s->fi); + const char * FUser = rpmfiFUser(s->fi); + const char * FGroup = rpmfiFGroup(s->fi); + + result = PyTuple_New(13); + if (FN == NULL) { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(result, 0, Py_None); + } else + PyTuple_SET_ITEM(result, 0, Py_BuildValue("s", FN)); + PyTuple_SET_ITEM(result, 1, PyLong_FromLongLong(FSize)); + PyTuple_SET_ITEM(result, 2, PyInt_FromLong(FMode)); + PyTuple_SET_ITEM(result, 3, PyInt_FromLong(FMtime)); + PyTuple_SET_ITEM(result, 4, PyInt_FromLong(FFlags)); + PyTuple_SET_ITEM(result, 5, PyInt_FromLong(FRdev)); + PyTuple_SET_ITEM(result, 6, PyInt_FromLong(FInode)); + PyTuple_SET_ITEM(result, 7, PyInt_FromLong(FNlink)); + PyTuple_SET_ITEM(result, 8, PyInt_FromLong(FState)); + PyTuple_SET_ITEM(result, 9, PyInt_FromLong(VFlags)); + if (FUser == NULL) { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(result, 10, Py_None); + } else + PyTuple_SET_ITEM(result, 10, Py_BuildValue("s", FUser)); + if (FGroup == NULL) { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(result, 11, Py_None); + } else + PyTuple_SET_ITEM(result, 11, Py_BuildValue("s", FGroup)); + PyTuple_SET_ITEM(result, 12, rpmfi_Digest(s)); + + } else + s->active = 0; + + return result; +} + +static struct PyMethodDef rpmfi_methods[] = { + {"FC", (PyCFunction)rpmfi_FC, METH_NOARGS, + NULL}, + {"FX", (PyCFunction)rpmfi_FX, METH_NOARGS, + NULL}, + {"DC", (PyCFunction)rpmfi_DC, METH_NOARGS, + NULL}, + {"DX", (PyCFunction)rpmfi_DX, METH_NOARGS, + NULL}, + {"BN", (PyCFunction)rpmfi_BN, METH_NOARGS, + NULL}, + {"DN", (PyCFunction)rpmfi_DN, METH_NOARGS, + NULL}, + {"FN", (PyCFunction)rpmfi_FN, METH_NOARGS, + NULL}, + {"FFlags", (PyCFunction)rpmfi_FFlags, METH_NOARGS, + NULL}, + {"VFlags", (PyCFunction)rpmfi_VFlags, METH_NOARGS, + NULL}, + {"FMode", (PyCFunction)rpmfi_FMode, METH_NOARGS, + NULL}, + {"FState", (PyCFunction)rpmfi_FState, METH_NOARGS, + NULL}, + {"MD5", (PyCFunction)rpmfi_Digest, METH_NOARGS, + NULL}, + {"Digest", (PyCFunction)rpmfi_Digest, METH_NOARGS, + NULL}, + {"FLink", (PyCFunction)rpmfi_FLink, METH_NOARGS, + NULL}, + {"FSize", (PyCFunction)rpmfi_FSize, METH_NOARGS, + NULL}, + {"FRdev", (PyCFunction)rpmfi_FRdev, METH_NOARGS, + NULL}, + {"FMtime", (PyCFunction)rpmfi_FMtime, METH_NOARGS, + NULL}, + {"FUser", (PyCFunction)rpmfi_FUser, METH_NOARGS, + NULL}, + {"FGroup", (PyCFunction)rpmfi_FGroup, METH_NOARGS, + NULL}, + {"FColor", (PyCFunction)rpmfi_FColor, METH_NOARGS, + NULL}, + {"FClass", (PyCFunction)rpmfi_FClass, METH_NOARGS, + NULL}, + {NULL, NULL} /* sentinel */ +}; + +/* ---------- */ + +static void +rpmfi_dealloc(rpmfiObject * s) +{ + s->fi = rpmfiFree(s->fi); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static int +rpmfi_length(rpmfiObject * s) +{ + return rpmfiFC(s->fi); +} + +static PyObject * +rpmfi_subscript(rpmfiObject * s, PyObject * key) +{ + int ix; + + if (!PyInt_Check(key)) { + PyErr_SetString(PyExc_TypeError, "integer expected"); + return NULL; + } + + ix = (int) PyInt_AsLong(key); + rpmfiSetFX(s->fi, ix); + return Py_BuildValue("s", rpmfiFN(s->fi)); +} + +static PyMappingMethods rpmfi_as_mapping = { + (lenfunc) rpmfi_length, /* mp_length */ + (binaryfunc) rpmfi_subscript, /* mp_subscript */ + (objobjargproc)0, /* mp_ass_subscript */ +}; + +static int rpmfi_init(rpmfiObject * s, PyObject *args, PyObject *kwds) +{ + s->active = 0; + return 0; +} + +static PyObject * rpmfi_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds) +{ + PyObject * to = NULL; + Header h = NULL; + rpmfi fi = NULL; + rpmTagVal tagN = RPMTAG_BASENAMES; + int flags = 0; + char * kwlist[] = {"header", "tag", "flags", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|Oi:rpmfi_init", kwlist, + hdrFromPyObject, &h, &to, &flags)) + return NULL; + + fi = rpmfiNew(NULL, h, tagN, flags); + + return rpmfi_Wrap(subtype, fi); +} + +static char rpmfi_doc[] = +""; + +PyTypeObject rpmfi_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.fi", /* tp_name */ + sizeof(rpmfiObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor) rpmfi_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + &rpmfi_as_mapping, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmfi_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc) rpmfi_iternext, /* tp_iternext */ + rpmfi_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc) rpmfi_init, /* tp_init */ + 0, /* tp_alloc */ + (newfunc) rpmfi_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +/* ---------- */ + +rpmfi fiFromFi(rpmfiObject * s) +{ + return s->fi; +} + +PyObject * rpmfi_Wrap(PyTypeObject *subtype, rpmfi fi) +{ + rpmfiObject *s = (rpmfiObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->fi = fi; + s->active = 0; + return (PyObject *) s; +} + diff --git a/python/rpmfi-py.h b/python/rpmfi-py.h new file mode 100644 index 0000000..604bf71 --- /dev/null +++ b/python/rpmfi-py.h @@ -0,0 +1,16 @@ +#ifndef H_RPMFI_PY +#define H_RPMFI_PY + +#include <rpm/rpmfi.h> + +typedef struct rpmfiObject_s rpmfiObject; + +extern PyTypeObject rpmfi_Type; + +#define rpmfiObject_Check(v) ((v)->ob_type == &rpmfi_Type) + +rpmfi fiFromFi(rpmfiObject * fi); + +PyObject * rpmfi_Wrap(PyTypeObject *subtype, rpmfi fi); + +#endif diff --git a/python/rpmii-py.c b/python/rpmii-py.c new file mode 100644 index 0000000..82817d8 --- /dev/null +++ b/python/rpmii-py.c @@ -0,0 +1,158 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmdb.h> + +#include "rpmii-py.h" +#include "header-py.h" + +#include "debug.h" + +/** \ingroup python + * \class Rpmii + * \brief A python rpm.ii key iterator object represents the keys of a + * database index. + * + * The rpm.ii class conains the following methods: + * - next() -> key Return the next key. + * + * To obtain a rpm.ii object to query the database used by a transaction, + * the ts.dbIndex(tag) method is used. + * + * Here's an example that prints the name of all installed packages: + * \code + * import rpm + * ts = rpm.TransactionSet() + * for name in ts.dbIndex("conflictname"): + * print name + * \endcode + * + * ts.dbIndex() can be used to get the packages containing the keys of interest + */ + +/** \ingroup python + * \name Class: Rpmii + */ + +struct rpmiiObject_s { + PyObject_HEAD + PyObject *md_dict; /*!< to look like PyModuleObject */ + PyObject *ref; /* for db/ts refcounting */ + rpmdbIndexIterator ii; +}; + +static PyObject * +rpmii_iternext(rpmiiObject * s) +{ + char * key; + size_t keylen; + if (s->ii == NULL || (rpmdbIndexIteratorNext(s->ii, (const void**)&key, &keylen)) != 0) { + s->ii = rpmdbIndexIteratorFree(s->ii); + return NULL; + } + return PyBytes_FromStringAndSize(key, keylen); +}; + +static PyObject * +rpmii_instances(rpmiiObject * s) +{ + int entries = rpmdbIndexIteratorNumPkgs(s->ii); + PyObject * list = PyList_New(0); + PyObject * tuple; + for (int i = 0; i < entries; i++) { + tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, + PyInt_FromLong(rpmdbIndexIteratorPkgOffset(s->ii, i))); + PyTuple_SET_ITEM(tuple, 1, + PyInt_FromLong(rpmdbIndexIteratorTagNum(s->ii, i))); + PyList_Append(list, tuple); + } + return list; +} + +static struct PyMethodDef rpmii_methods[] = { + {"instances", (PyCFunction) rpmii_instances, METH_NOARGS, NULL}, + {NULL, NULL} /* sentinel */ +}; + +static void rpmii_dealloc(rpmiiObject * s) +{ + s->ii = rpmdbIndexIteratorFree(s->ii); + Py_DECREF(s->ref); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static int rpmii_bool(rpmiiObject *s) +{ + return (s->ii != NULL); +} + +static PyNumberMethods rpmii_as_number = { + 0, /* nb_add */ + 0, /* nb_subtract */ + 0, /* nb_multiply */ + 0, /* nb_divide */ + 0, /* nb_remainder */ + 0, /* nb_divmod */ + 0, /* nb_power */ + 0, /* nb_negative */ + 0, /* nb_positive */ + 0, /* nb_absolute */ + (inquiry)rpmii_bool, /* nb_bool/nonzero */ +}; + +static char rpmii_doc[] = +""; + +PyTypeObject rpmii_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.ii", /* tp_name */ + sizeof(rpmiiObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) rpmii_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + &rpmii_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmii_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc) rpmii_iternext, /* tp_iternext */ + rpmii_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * rpmii_Wrap(PyTypeObject *subtype, rpmdbIndexIterator ii, PyObject *s) +{ + rpmiiObject * iio = (rpmiiObject *)subtype->tp_alloc(subtype, 0); + if (iio == NULL) return NULL; + + iio->ii = ii; + iio->ref = s; + Py_INCREF(iio->ref); + return (PyObject *) iio; +} diff --git a/python/rpmii-py.h b/python/rpmii-py.h new file mode 100644 index 0000000..bcfc5ff --- /dev/null +++ b/python/rpmii-py.h @@ -0,0 +1,12 @@ +#ifndef H_RPMII_PY +#define H_RPMII_PY + +typedef struct rpmiiObject_s rpmiiObject; + +extern PyTypeObject rpmii_Type; + +#define rpmiiObject_Check(v) ((v)->ob_type == &rpmii_Type) + +PyObject * rpmii_Wrap(PyTypeObject *subtype, rpmdbIndexIterator ii, PyObject *s); + +#endif diff --git a/python/rpmkeyring-py.c b/python/rpmkeyring-py.c new file mode 100644 index 0000000..d5f131e --- /dev/null +++ b/python/rpmkeyring-py.c @@ -0,0 +1,202 @@ +#include "rpmsystem-py.h" +#include <rpm/rpmkeyring.h> +#include "rpmkeyring-py.h" + +struct rpmPubkeyObject_s { + PyObject_HEAD + PyObject *md_dict; + rpmPubkey pubkey; +}; + +static void rpmPubkey_dealloc(rpmPubkeyObject * s) +{ + s->pubkey = rpmPubkeyFree(s->pubkey); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static PyObject *rpmPubkey_new(PyTypeObject *subtype, + PyObject *args, PyObject *kwds) +{ + PyObject *key; + char *kwlist[] = { "key", NULL }; + rpmPubkey pubkey = NULL; + uint8_t *pkt; + size_t pktlen; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "S", kwlist, &key)) + return NULL; + + if (pgpParsePkts(PyBytes_AsString(key), &pkt, &pktlen) <= 0) { + PyErr_SetString(PyExc_ValueError, "invalid pubkey"); + return NULL; + } + pubkey = rpmPubkeyNew(pkt, pktlen); + + return rpmPubkey_Wrap(subtype, pubkey); +} + +static PyObject * rpmPubkey_Base64(rpmPubkeyObject *s) +{ + char *b64 = rpmPubkeyBase64(s->pubkey); + PyObject *res = Py_BuildValue("s", b64); + free(b64); + return res; +} + +static struct PyMethodDef rpmPubkey_methods[] = { + { "base64", (PyCFunction) rpmPubkey_Base64, METH_NOARGS, NULL }, + { NULL } +}; + +static char rpmPubkey_doc[] = ""; + +PyTypeObject rpmPubkey_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.pubkey", /* tp_name */ + sizeof(rpmPubkeyObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) rpmPubkey_dealloc,/* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmPubkey_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rpmPubkey_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + rpmPubkey_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +struct rpmKeyringObject_s { + PyObject_HEAD + PyObject *md_dict; + rpmKeyring keyring; +}; + +static void rpmKeyring_dealloc(rpmKeyringObject * s) +{ + rpmKeyringFree(s->keyring); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static PyObject *rpmKeyring_new(PyTypeObject *subtype, + PyObject *args, PyObject *kwds) +{ + rpmKeyring keyring = rpmKeyringNew(); + return rpmKeyring_Wrap(subtype, keyring); +} + +static PyObject *rpmKeyring_addKey(rpmKeyringObject *s, PyObject *arg) +{ + rpmPubkeyObject *pubkey = NULL; + + if (!PyArg_Parse(arg, "O!", &rpmPubkey_Type, &pubkey)) + return NULL; + + return Py_BuildValue("i", rpmKeyringAddKey(s->keyring, pubkey->pubkey)); +}; + +static struct PyMethodDef rpmKeyring_methods[] = { + { "addKey", (PyCFunction) rpmKeyring_addKey, METH_O, + NULL }, + {NULL, NULL} /* sentinel */ +}; + +static char rpmKeyring_doc[] = +""; + +PyTypeObject rpmKeyring_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.keyring", /* tp_name */ + sizeof(rpmKeyringObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) rpmKeyring_dealloc,/* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmKeyring_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rpmKeyring_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + rpmKeyring_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * rpmPubkey_Wrap(PyTypeObject *subtype, rpmPubkey pubkey) +{ + rpmPubkeyObject *s = (rpmPubkeyObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->pubkey = pubkey; + return (PyObject*) s; +} + +PyObject * rpmKeyring_Wrap(PyTypeObject *subtype, rpmKeyring keyring) +{ + rpmKeyringObject *s = (rpmKeyringObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->keyring = keyring; + return (PyObject*) s; +} + +int rpmKeyringFromPyObject(PyObject *item, rpmKeyring *keyring) +{ + rpmKeyringObject *kro; + if (!PyArg_Parse(item, "O!", &rpmKeyring_Type, &kro)) + return 0; + *keyring = kro->keyring; + return 1; +} diff --git a/python/rpmkeyring-py.h b/python/rpmkeyring-py.h new file mode 100644 index 0000000..4ba017c --- /dev/null +++ b/python/rpmkeyring-py.h @@ -0,0 +1,16 @@ +#ifndef H_RPMKEYRING_PY +#define H_RPMKEYRING_PY + +#include <rpm/rpmtypes.h> + +typedef struct rpmPubkeyObject_s rpmPubkeyObject; +typedef struct rpmKeyringObject_s rpmKeyringObject; + +extern PyTypeObject rpmKeyring_Type; +extern PyTypeObject rpmPubkey_Type; + +PyObject * rpmPubkey_Wrap(PyTypeObject *subtype, rpmPubkey pubkey); +PyObject * rpmKeyring_Wrap(PyTypeObject *subtype, rpmKeyring keyring); + +int rpmKeyringFromPyObject(PyObject *item, rpmKeyring *keyring); +#endif diff --git a/python/rpmmacro-py.c b/python/rpmmacro-py.c new file mode 100644 index 0000000..dec8de0 --- /dev/null +++ b/python/rpmmacro-py.c @@ -0,0 +1,58 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmmacro.h> + +#include "rpmmacro-py.h" + +#include "debug.h" + +PyObject * +rpmmacro_AddMacro(PyObject * self, PyObject * args, PyObject * kwds) +{ + char * name, * val; + char * kwlist[] = {"name", "value", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss:AddMacro", kwlist, + &name, &val)) + return NULL; + + addMacro(NULL, name, NULL, val, -1); + + Py_RETURN_NONE; +} + +PyObject * +rpmmacro_DelMacro(PyObject * self, PyObject * args, PyObject * kwds) +{ + char * name; + char * kwlist[] = {"name", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:DelMacro", kwlist, &name)) + return NULL; + + delMacro(NULL, name); + + Py_RETURN_NONE; +} + +PyObject * +rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds) +{ + char *macro; + PyObject *res; + int num = 0; + char * kwlist[] = {"macro", "numeric", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, ¯o, &num)) + return NULL; + + if (num) { + res = Py_BuildValue("i", rpmExpandNumeric(macro)); + } else { + char *str = rpmExpand(macro, NULL); + res = Py_BuildValue("s", str); + free(str); + } + return res; +} + diff --git a/python/rpmmacro-py.h b/python/rpmmacro-py.h new file mode 100644 index 0000000..c9abffe --- /dev/null +++ b/python/rpmmacro-py.h @@ -0,0 +1,8 @@ +#ifndef H_RPMMACRO_PY +#define H_RPMMACRO_PY + +PyObject * rpmmacro_AddMacro(PyObject * self, PyObject * args, PyObject * kwds); +PyObject * rpmmacro_DelMacro(PyObject * self, PyObject * args, PyObject * kwds); +PyObject * rpmmacro_ExpandMacro(PyObject * self, PyObject * args, PyObject * kwds); + +#endif diff --git a/python/rpmmi-py.c b/python/rpmmi-py.c new file mode 100644 index 0000000..0b1c27a --- /dev/null +++ b/python/rpmmi-py.c @@ -0,0 +1,220 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmdb.h> + +#include "rpmmi-py.h" +#include "header-py.h" + +#include "debug.h" + +/** \ingroup python + * \class Rpmmi + * \brief A python rpm.mi match iterator object represents the result of a + * database query. + * + * Instances of the rpm.mi object provide access to headers that match + * certain criteria. Typically, a primary index is accessed to find + * a set of headers that contain a key, and each header is returned + * serially. + * + * The rpm.mi class conains the following methods: + * - next() -> hdr Return the next header that matches. + * + * - pattern(tag,mire,pattern) Specify secondary match criteria. + * + * To obtain a rpm.mi object to query the database used by a transaction, + * the ts.match(tag,key,len) method is used. + * + * Here's an example that prints the name of all installed packages: + * \code + * import rpm + * ts = rpm.TransactionSet() + * for h in ts.dbMatch(): + * print h['name'] + * \endcode + * + * Here's a more typical example that uses the Name index to retrieve + * all installed kernel(s): + * \code + * import rpm + * ts = rpm.TransactionSet() + * mi = ts.dbMatch('name', "kernel") + * for h in mi: + * print "%s-%s-%s" % (h['name'], h['version'], h['release']) + * \endcode + * + * Finally, here's an example that retrieves all packages whose name + * matches the glob expression "XFree*": + * \code + * import rpm + * ts = rpm.TransactionSet() + * mi = ts.dbMatch() + * mi.pattern('name', rpm.RPMMIRE_GLOB, "XFree*") + * for h in mi: + * print "%s-%s-%s" % (h['name'], h['version'], h['release']) + * \endcode + * + */ + +/** \ingroup python + * \name Class: Rpmmi + */ + +struct rpmmiObject_s { + PyObject_HEAD + PyObject *md_dict; /*!< to look like PyModuleObject */ + PyObject *ref; /* for db/ts refcounting */ + rpmdbMatchIterator mi; +} ; + +static PyObject * +rpmmi_iternext(rpmmiObject * s) +{ + Header h; + + if (s->mi == NULL || (h = rpmdbNextIterator(s->mi)) == NULL) { + s->mi = rpmdbFreeIterator(s->mi); + return NULL; + } + return hdr_Wrap(&hdr_Type, h); +} + +static PyObject * +rpmmi_Instance(rpmmiObject * s) +{ + int rc = 0; + + if (s->mi != NULL) + rc = rpmdbGetIteratorOffset(s->mi); + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmmi_Count(rpmmiObject * s) +{ + DEPRECATED_METHOD("use len(mi) instead"); + return Py_BuildValue("i", PyMapping_Size((PyObject *)s)); +} + +static PyObject * +rpmmi_Pattern(rpmmiObject * s, PyObject * args, PyObject * kwds) +{ + int type; + char * pattern; + rpmTagVal tag; + char * kwlist[] = {"tag", "type", "patern", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&is:Pattern", kwlist, + tagNumFromPyObject, &tag, &type, &pattern)) + return NULL; + + rpmdbSetIteratorRE(s->mi, tag, type, pattern); + + Py_RETURN_NONE; +} + +static struct PyMethodDef rpmmi_methods[] = { + {"instance", (PyCFunction) rpmmi_Instance, METH_NOARGS, + NULL }, + {"count", (PyCFunction) rpmmi_Count, METH_NOARGS, +"Deprecated, use len(mi) instead.\n" }, + {"pattern", (PyCFunction) rpmmi_Pattern, METH_VARARGS|METH_KEYWORDS, +"mi.pattern(TagN, mire_type, pattern)\n\ +- Set a secondary match pattern on tags from retrieved header.\n" }, + {NULL, NULL} /* sentinel */ +}; + +static void rpmmi_dealloc(rpmmiObject * s) +{ + s->mi = rpmdbFreeIterator(s->mi); + Py_DECREF(s->ref); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static Py_ssize_t rpmmi_length(rpmmiObject * s) +{ + return s->mi ? rpmdbGetIteratorCount(s->mi) : 0; +} + +static int rpmmi_bool(rpmmiObject *s) +{ + return (s->mi != NULL); +} + +PyMappingMethods rpmmi_as_mapping = { + (lenfunc) rpmmi_length, /* mp_length */ + 0, +}; + +static PyNumberMethods rpmmi_as_number = { + 0, /* nb_add */ + 0, /* nb_subtract */ + 0, /* nb_multiply */ + 0, /* nb_divide */ + 0, /* nb_remainder */ + 0, /* nb_divmod */ + 0, /* nb_power */ + 0, /* nb_negative */ + 0, /* nb_positive */ + 0, /* nb_absolute */ + (inquiry)rpmmi_bool, /* nb_bool/nonzero */ +}; + +static char rpmmi_doc[] = +""; + +PyTypeObject rpmmi_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.mi", /* tp_name */ + sizeof(rpmmiObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) rpmmi_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + &rpmmi_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + &rpmmi_as_mapping, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmmi_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc) rpmmi_iternext, /* tp_iternext */ + rpmmi_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * rpmmi_Wrap(PyTypeObject *subtype, rpmdbMatchIterator mi, PyObject *s) +{ + rpmmiObject * mio = (rpmmiObject *)subtype->tp_alloc(subtype, 0); + if (mio == NULL) return NULL; + + mio->mi = mi; + mio->ref = s; + Py_INCREF(mio->ref); + return (PyObject *) mio; +} + diff --git a/python/rpmmi-py.h b/python/rpmmi-py.h new file mode 100644 index 0000000..ef07c72 --- /dev/null +++ b/python/rpmmi-py.h @@ -0,0 +1,12 @@ +#ifndef H_RPMMI_PY +#define H_RPMMI_PY + +typedef struct rpmmiObject_s rpmmiObject; + +extern PyTypeObject rpmmi_Type; + +#define rpmmiObject_Check(v) ((v)->ob_type == &rpmmi_Type) + +PyObject * rpmmi_Wrap(PyTypeObject *subtype, rpmdbMatchIterator mi, PyObject *s); + +#endif diff --git a/python/rpmmodule.c b/python/rpmmodule.c new file mode 100644 index 0000000..0b69d4f --- /dev/null +++ b/python/rpmmodule.c @@ -0,0 +1,504 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmlib.h> /* rpmMachineScore, rpmReadConfigFiles */ +#include <rpm/rpmtag.h> +#include <rpm/rpmdb.h> +#include <rpm/rpmsq.h> +#include <rpm/rpmlog.h> + +#include "header-py.h" +#include "rpmds-py.h" +#include "rpmfd-py.h" +#include "rpmfi-py.h" +#include "rpmkeyring-py.h" +#include "rpmmi-py.h" +#include "rpmii-py.h" +#include "rpmps-py.h" +#include "rpmmacro-py.h" +#include "rpmtd-py.h" +#include "rpmte-py.h" +#include "rpmts-py.h" + +#include "debug.h" + +/** \ingroup python + * \name Module: rpm + */ + +PyObject * pyrpmError; + +static PyObject * archScore(PyObject * self, PyObject * arg) +{ + char * arch; + + if (!PyArg_Parse(arg, "s", &arch)) + return NULL; + + return Py_BuildValue("i", rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch)); +} + +static PyObject * signalCaught(PyObject *self, PyObject *o) +{ + int signo; + if (!PyArg_Parse(o, "i", &signo)) return NULL; + + return PyBool_FromLong(rpmsqIsCaught(signo)); +} + +static PyObject * checkSignals(PyObject * self) +{ + rpmdbCheckSignals(); + Py_RETURN_NONE; +} + +static PyObject * setLogFile (PyObject * self, PyObject *arg) +{ + FILE *fp; + int fdno = PyObject_AsFileDescriptor(arg); + + if (fdno >= 0) { + /* XXX we dont know the mode here.. guessing append for now */ + fp = fdopen(fdno, "a"); + if (fp == NULL) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + } else if (arg == Py_None) { + fp = NULL; + } else { + PyErr_SetString(PyExc_TypeError, "file object or None expected"); + return NULL; + } + + (void) rpmlogSetFile(fp); + Py_RETURN_NONE; +} + +static PyObject * +setVerbosity (PyObject * self, PyObject * arg) +{ + int level; + + if (!PyArg_Parse(arg, "i", &level)) + return NULL; + + rpmSetVerbosity(level); + + Py_RETURN_NONE; +} + +static PyObject * +setEpochPromote (PyObject * self, PyObject * arg) +{ + if (!PyArg_Parse(arg, "i", &_rpmds_nopromote)) + return NULL; + + Py_RETURN_NONE; +} + +static PyObject * setStats (PyObject * self, PyObject * arg) +{ + if (!PyArg_Parse(arg, "i", &_rpmts_stats)) + return NULL; + + Py_RETURN_NONE; +} + +static PyObject * doLog(PyObject * self, PyObject * args, PyObject *kwds) +{ + int code; + const char *msg; + char * kwlist[] = {"code", "msg", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &code, &msg)) + return NULL; + + rpmlog(code, "%s", msg); + Py_RETURN_NONE; +} + +static PyMethodDef rpmModuleMethods[] = { + { "addMacro", (PyCFunction) rpmmacro_AddMacro, METH_VARARGS|METH_KEYWORDS, + NULL }, + { "delMacro", (PyCFunction) rpmmacro_DelMacro, METH_VARARGS|METH_KEYWORDS, + NULL }, + { "expandMacro", (PyCFunction) rpmmacro_ExpandMacro, METH_VARARGS|METH_KEYWORDS, + NULL }, + + { "archscore", (PyCFunction) archScore, METH_O, + NULL }, + + { "signalCaught", (PyCFunction) signalCaught, METH_O, + NULL }, + { "checkSignals", (PyCFunction) checkSignals, METH_NOARGS, + NULL }, + + { "mergeHeaderListFromFD", (PyCFunction) rpmMergeHeadersFromFD, METH_VARARGS|METH_KEYWORDS, + NULL }, + + { "log", (PyCFunction) doLog, METH_VARARGS|METH_KEYWORDS, + NULL }, + { "setLogFile", (PyCFunction) setLogFile, METH_O, + NULL }, + + { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS|METH_KEYWORDS, + NULL }, + { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS|METH_KEYWORDS, + NULL }, + { "setVerbosity", (PyCFunction) setVerbosity, METH_O, + NULL }, + { "setEpochPromote", (PyCFunction) setEpochPromote, METH_O, + NULL }, + { "setStats", (PyCFunction) setStats, METH_O, + NULL }, + + { NULL } +} ; + +/* +* Force clean up of open iterators and dbs on exit. +*/ +static void rpm_exithook(void) +{ + rpmdbCheckTerminate(1); +} + +static char rpm__doc__[] = +""; + +/* + * Add rpm tag dictionaries to the module + */ +static void addRpmTags(PyObject *module) +{ + PyObject *pyval, *pyname, *dict = PyDict_New(); + rpmtd names = rpmtdNew(); + rpmTagGetNames(names, 1); + const char *tagname, *shortname; + rpmTagVal tagval; + + while ((tagname = rpmtdNextString(names))) { + shortname = tagname + strlen("RPMTAG_"); + tagval = rpmTagGetValue(shortname); + + PyModule_AddIntConstant(module, tagname, tagval); + pyval = PyInt_FromLong(tagval); + pyname = Py_BuildValue("s", shortname); + PyDict_SetItem(dict, pyval, pyname); + Py_DECREF(pyval); + Py_DECREF(pyname); + } + PyModule_AddObject(module, "tagnames", dict); + rpmtdFreeData(names); + rpmtdFree(names); +} + +/* + Do any common preliminary work before python 2 vs python 3 module creation: +*/ +static int prepareInitModule(void) +{ + if (PyType_Ready(&hdr_Type) < 0) return 0; + if (PyType_Ready(&rpmds_Type) < 0) return 0; + if (PyType_Ready(&rpmfd_Type) < 0) return 0; + if (PyType_Ready(&rpmfi_Type) < 0) return 0; + if (PyType_Ready(&rpmKeyring_Type) < 0) return 0; + if (PyType_Ready(&rpmmi_Type) < 0) return 0; + if (PyType_Ready(&rpmii_Type) < 0) return 0; + if (PyType_Ready(&rpmProblem_Type) < 0) return 0; + if (PyType_Ready(&rpmPubkey_Type) < 0) return 0; +#if 0 + if (PyType_Ready(&rpmtd_Type) < 0) return 0; +#endif + if (PyType_Ready(&rpmte_Type) < 0) return 0; + if (PyType_Ready(&rpmts_Type) < 0) return 0; + + return 1; +} +static int initModule(PyObject *m); + +#if PY_MAJOR_VERSION >= 3 +static int rpmModuleTraverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(pyrpmError); + return 0; +} + +static int rpmModuleClear(PyObject *m) { + Py_CLEAR(pyrpmError); + return 0; +} + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_rpm", /* m_name */ + rpm__doc__, /* m_doc */ + 0, /* m_size */ + rpmModuleMethods, + NULL, /* m_reload */ + rpmModuleTraverse, + rpmModuleClear, + NULL /* m_free */ +}; + +PyObject * +PyInit__rpm(void); + +PyObject * +PyInit__rpm(void) +{ + PyObject * m; + if (!prepareInitModule()) return NULL; + m = PyModule_Create(&moduledef); + initModule(m); + return m; +} +#else +void init_rpm(void); /* XXX eliminate gcc warning */ +void init_rpm(void) +{ + PyObject * m; + + if (!prepareInitModule()) return; + m = Py_InitModule3("_rpm", rpmModuleMethods, rpm__doc__); + if (m == NULL) + return; + initModule(m); +} +#endif + +/* Shared python2/3 module initialization: */ +static int initModule(PyObject *m) +{ + PyObject * d; + + /* + * treat error to register rpm cleanup hook as fatal, tracebacks + * can and will leave stale locks around if we can't clean up + */ + if (Py_AtExit(rpm_exithook) == -1) + return 0; + + rpmReadConfigFiles(NULL, NULL); + + d = PyModule_GetDict(m); + + pyrpmError = PyErr_NewException("_rpm.error", NULL, NULL); + if (pyrpmError != NULL) + PyDict_SetItemString(d, "error", pyrpmError); + + Py_INCREF(&hdr_Type); + PyModule_AddObject(m, "hdr", (PyObject *) &hdr_Type); + + Py_INCREF(&rpmds_Type); + PyModule_AddObject(m, "ds", (PyObject *) &rpmds_Type); + + Py_INCREF(&rpmfd_Type); + PyModule_AddObject(m, "fd", (PyObject *) &rpmfd_Type); + + Py_INCREF(&rpmfi_Type); + PyModule_AddObject(m, "fi", (PyObject *) &rpmfi_Type); + + Py_INCREF(&rpmKeyring_Type); + PyModule_AddObject(m, "keyring", (PyObject *) &rpmKeyring_Type); + + Py_INCREF(&rpmmi_Type); + PyModule_AddObject(m, "mi", (PyObject *) &rpmmi_Type); + + Py_INCREF(&rpmii_Type); + PyModule_AddObject(m, "ii", (PyObject *) &rpmii_Type); + + Py_INCREF(&rpmProblem_Type); + PyModule_AddObject(m, "prob", (PyObject *) &rpmProblem_Type); + + Py_INCREF(&rpmPubkey_Type); + PyModule_AddObject(m, "pubkey", (PyObject *) &rpmPubkey_Type); + +#if 0 + Py_INCREF(&rpmtd_Type); + PyModule_AddObject(m, "td", (PyObject *) &rpmtd_Type); +#endif + + Py_INCREF(&rpmte_Type); + PyModule_AddObject(m, "te", (PyObject *) &rpmte_Type); + + Py_INCREF(&rpmts_Type); + PyModule_AddObject(m, "ts", (PyObject *) &rpmts_Type); + + addRpmTags(m); + + PyModule_AddStringConstant(m, "__version__", RPMVERSION); + +#define REGISTER_ENUM(val) PyModule_AddIntConstant(m, #val, val) + + REGISTER_ENUM(RPMTAG_NOT_FOUND); + + REGISTER_ENUM(RPMRC_OK); + REGISTER_ENUM(RPMRC_NOTFOUND); + REGISTER_ENUM(RPMRC_FAIL); + REGISTER_ENUM(RPMRC_NOTTRUSTED); + REGISTER_ENUM(RPMRC_NOKEY); + + REGISTER_ENUM(RPMFILE_STATE_NORMAL); + REGISTER_ENUM(RPMFILE_STATE_REPLACED); + REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED); + REGISTER_ENUM(RPMFILE_STATE_NETSHARED); + REGISTER_ENUM(RPMFILE_STATE_WRONGCOLOR); + + REGISTER_ENUM(RPMFILE_CONFIG); + REGISTER_ENUM(RPMFILE_DOC); + REGISTER_ENUM(RPMFILE_MISSINGOK); + REGISTER_ENUM(RPMFILE_NOREPLACE); + REGISTER_ENUM(RPMFILE_GHOST); + REGISTER_ENUM(RPMFILE_LICENSE); + REGISTER_ENUM(RPMFILE_README); + REGISTER_ENUM(RPMFILE_EXCLUDE); + REGISTER_ENUM(RPMFILE_UNPATCHED); + REGISTER_ENUM(RPMFILE_PUBKEY); + + REGISTER_ENUM(RPMDEP_SENSE_REQUIRES); + REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS); + + REGISTER_ENUM(RPMSENSE_ANY); + REGISTER_ENUM(RPMSENSE_LESS); + REGISTER_ENUM(RPMSENSE_GREATER); + REGISTER_ENUM(RPMSENSE_EQUAL); + REGISTER_ENUM(RPMSENSE_PREREQ); + REGISTER_ENUM(RPMSENSE_INTERP); + REGISTER_ENUM(RPMSENSE_SCRIPT_PRE); + REGISTER_ENUM(RPMSENSE_SCRIPT_POST); + REGISTER_ENUM(RPMSENSE_SCRIPT_PREUN); + REGISTER_ENUM(RPMSENSE_SCRIPT_POSTUN); + REGISTER_ENUM(RPMSENSE_SCRIPT_VERIFY); + REGISTER_ENUM(RPMSENSE_FIND_REQUIRES); + REGISTER_ENUM(RPMSENSE_FIND_PROVIDES); + REGISTER_ENUM(RPMSENSE_TRIGGERIN); + REGISTER_ENUM(RPMSENSE_TRIGGERUN); + REGISTER_ENUM(RPMSENSE_TRIGGERPOSTUN); + REGISTER_ENUM(RPMSENSE_RPMLIB); + REGISTER_ENUM(RPMSENSE_TRIGGERPREIN); + REGISTER_ENUM(RPMSENSE_KEYRING); + REGISTER_ENUM(RPMSENSE_CONFIG); + + REGISTER_ENUM(RPMTRANS_FLAG_TEST); + REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS); + REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS); + REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB); + REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS); + REGISTER_ENUM(RPMTRANS_FLAG_NODOCS); + REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES); + REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE); + REGISTER_ENUM(RPMTRANS_FLAG_NOCONTEXTS); + REGISTER_ENUM(RPMTRANS_FLAG_REPACKAGE); + REGISTER_ENUM(RPMTRANS_FLAG_REVERSE); + REGISTER_ENUM(RPMTRANS_FLAG_NOPRE); + REGISTER_ENUM(RPMTRANS_FLAG_NOPOST); + REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERPREIN); + REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERIN); + REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERUN); + REGISTER_ENUM(RPMTRANS_FLAG_NOPREUN); + REGISTER_ENUM(RPMTRANS_FLAG_NOPOSTUN); + REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERPOSTUN); + REGISTER_ENUM(RPMTRANS_FLAG_NOMD5); + REGISTER_ENUM(RPMTRANS_FLAG_NOFILEDIGEST); + REGISTER_ENUM(RPMTRANS_FLAG_NOSUGGEST); + REGISTER_ENUM(RPMTRANS_FLAG_ADDINDEPS); + REGISTER_ENUM(RPMTRANS_FLAG_NOCONFIGS); + + REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS); + REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH); + REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG); + REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE); + REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES); + REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES); + REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE); + REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE); + REGISTER_ENUM(RPMPROB_FILTER_DISKNODES); + + REGISTER_ENUM(RPMCALLBACK_UNKNOWN); + REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS); + REGISTER_ENUM(RPMCALLBACK_INST_START); + REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE); + REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE); + REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS); + REGISTER_ENUM(RPMCALLBACK_TRANS_START); + REGISTER_ENUM(RPMCALLBACK_TRANS_STOP); + REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS); + REGISTER_ENUM(RPMCALLBACK_UNINST_START); + REGISTER_ENUM(RPMCALLBACK_UNINST_STOP); + REGISTER_ENUM(RPMCALLBACK_REPACKAGE_PROGRESS); + REGISTER_ENUM(RPMCALLBACK_REPACKAGE_START); + REGISTER_ENUM(RPMCALLBACK_REPACKAGE_STOP); + REGISTER_ENUM(RPMCALLBACK_UNPACK_ERROR); + REGISTER_ENUM(RPMCALLBACK_CPIO_ERROR); + REGISTER_ENUM(RPMCALLBACK_SCRIPT_ERROR); + + REGISTER_ENUM(RPMPROB_BADARCH); + REGISTER_ENUM(RPMPROB_BADOS); + REGISTER_ENUM(RPMPROB_PKG_INSTALLED); + REGISTER_ENUM(RPMPROB_BADRELOCATE); + REGISTER_ENUM(RPMPROB_REQUIRES); + REGISTER_ENUM(RPMPROB_CONFLICT); + REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT); + REGISTER_ENUM(RPMPROB_FILE_CONFLICT); + REGISTER_ENUM(RPMPROB_OLDPACKAGE); + REGISTER_ENUM(RPMPROB_DISKSPACE); + REGISTER_ENUM(RPMPROB_DISKNODES); + REGISTER_ENUM(RPMPROB_OBSOLETES); + + REGISTER_ENUM(VERIFY_DIGEST); + REGISTER_ENUM(VERIFY_SIGNATURE); + + REGISTER_ENUM(RPMLOG_EMERG); + REGISTER_ENUM(RPMLOG_ALERT); + REGISTER_ENUM(RPMLOG_CRIT); + REGISTER_ENUM(RPMLOG_ERR); + REGISTER_ENUM(RPMLOG_WARNING); + REGISTER_ENUM(RPMLOG_NOTICE); + REGISTER_ENUM(RPMLOG_INFO); + REGISTER_ENUM(RPMLOG_DEBUG); + + REGISTER_ENUM(RPMMIRE_DEFAULT); + REGISTER_ENUM(RPMMIRE_STRCMP); + REGISTER_ENUM(RPMMIRE_REGEX); + REGISTER_ENUM(RPMMIRE_GLOB); + + REGISTER_ENUM(RPMVSF_DEFAULT); + REGISTER_ENUM(RPMVSF_NOHDRCHK); + REGISTER_ENUM(RPMVSF_NEEDPAYLOAD); + REGISTER_ENUM(RPMVSF_NOSHA1HEADER); + REGISTER_ENUM(RPMVSF_NOMD5HEADER); + REGISTER_ENUM(RPMVSF_NODSAHEADER); + REGISTER_ENUM(RPMVSF_NORSAHEADER); + REGISTER_ENUM(RPMVSF_NOSHA1); + REGISTER_ENUM(RPMVSF_NOMD5); + REGISTER_ENUM(RPMVSF_NODSA); + REGISTER_ENUM(RPMVSF_NORSA); + REGISTER_ENUM(_RPMVSF_NODIGESTS); + REGISTER_ENUM(_RPMVSF_NOSIGNATURES); + REGISTER_ENUM(_RPMVSF_NOHEADER); + REGISTER_ENUM(_RPMVSF_NOPAYLOAD); + + REGISTER_ENUM(TR_ADDED); + REGISTER_ENUM(TR_REMOVED); + + REGISTER_ENUM(RPMDBI_PACKAGES); + REGISTER_ENUM(RPMDBI_LABEL); + REGISTER_ENUM(RPMDBI_NAME); + REGISTER_ENUM(RPMDBI_BASENAMES); + REGISTER_ENUM(RPMDBI_GROUP); + REGISTER_ENUM(RPMDBI_REQUIRENAME); + REGISTER_ENUM(RPMDBI_PROVIDENAME); + REGISTER_ENUM(RPMDBI_CONFLICTNAME); + REGISTER_ENUM(RPMDBI_OBSOLETENAME); + REGISTER_ENUM(RPMDBI_TRIGGERNAME); + REGISTER_ENUM(RPMDBI_DIRNAMES); + REGISTER_ENUM(RPMDBI_INSTALLTID); + REGISTER_ENUM(RPMDBI_SIGMD5); + REGISTER_ENUM(RPMDBI_SHA1HEADER); + + REGISTER_ENUM(HEADERCONV_EXPANDFILELIST); + REGISTER_ENUM(HEADERCONV_COMPRESSFILELIST); + REGISTER_ENUM(HEADERCONV_RETROFIT_V3); + + return 1; +} + diff --git a/python/rpmps-py.c b/python/rpmps-py.c new file mode 100644 index 0000000..fa7e91e --- /dev/null +++ b/python/rpmps-py.c @@ -0,0 +1,141 @@ +#include "rpmsystem-py.h" + +#include "rpmps-py.h" + +#include "debug.h" + +struct rpmProblemObject_s { + PyObject_HEAD + PyObject *md_dict; + rpmProblem prob; +}; + +static char rpmprob_doc[] = +""; + +static PyObject *rpmprob_get_type(rpmProblemObject *s, void *closure) +{ + return Py_BuildValue("i", rpmProblemGetType(s->prob)); +} + +static PyObject *rpmprob_get_pkgnevr(rpmProblemObject *s, void *closure) +{ + return Py_BuildValue("s", rpmProblemGetPkgNEVR(s->prob)); +} + +static PyObject *rpmprob_get_altnevr(rpmProblemObject *s, void *closure) +{ + return Py_BuildValue("s", rpmProblemGetAltNEVR(s->prob)); +} + +static PyObject *rpmprob_get_key(rpmProblemObject *s, void *closure) +{ + fnpyKey key = rpmProblemGetKey(s->prob); + if (key) { + return Py_BuildValue("O", rpmProblemGetKey(s->prob)); + } else { + Py_RETURN_NONE; + } +} + +static PyObject *rpmprob_get_str(rpmProblemObject *s, void *closure) +{ + return Py_BuildValue("s", rpmProblemGetStr(s->prob)); +} + +static PyObject *rpmprob_get_num(rpmProblemObject *s, void *closure) +{ + return Py_BuildValue("L", rpmProblemGetDiskNeed(s->prob)); +} + +static PyGetSetDef rpmprob_getseters[] = { + { "type", (getter)rpmprob_get_type, NULL, NULL }, + { "pkgNEVR", (getter)rpmprob_get_pkgnevr, NULL, NULL }, + { "altNEVR", (getter)rpmprob_get_altnevr, NULL, NULL }, + { "key", (getter)rpmprob_get_key, NULL, NULL }, + { "_str", (getter)rpmprob_get_str, NULL, NULL }, + { "_num", (getter)rpmprob_get_num, NULL, NULL }, + { NULL } +}; + +static PyObject *rpmprob_str(rpmProblemObject *s) +{ + char *str = rpmProblemString(s->prob); + PyObject *res = Py_BuildValue("s", str); + free(str); + return res; +} + +static void rpmprob_dealloc(rpmProblemObject *s) +{ + s->prob = rpmProblemFree(s->prob); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +PyTypeObject rpmProblem_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.prob", /* tp_name */ + sizeof(rpmProblemObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)rpmprob_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)rpmprob_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmprob_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + rpmprob_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject *rpmprob_Wrap(PyTypeObject *subtype, rpmProblem prob) +{ + rpmProblemObject * s = (rpmProblemObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->prob = rpmProblemLink(prob); + return (PyObject *) s; +} + +PyObject *rpmps_AsList(rpmps ps) +{ + PyObject *problems = PyList_New(0); + rpmpsi psi = rpmpsInitIterator(ps); + rpmProblem prob; + + while ((prob = rpmpsiNext(psi))) { + PyObject *pyprob = rpmprob_Wrap(&rpmProblem_Type, prob); + PyList_Append(problems, pyprob); + Py_DECREF(pyprob); + } + rpmpsFreeIterator(psi); + return problems; +} diff --git a/python/rpmps-py.h b/python/rpmps-py.h new file mode 100644 index 0000000..4d7efc8 --- /dev/null +++ b/python/rpmps-py.h @@ -0,0 +1,16 @@ +#ifndef H_RPMPS_PY +#define H_RPMPS_PY + +#include <rpm/rpmps.h> + +typedef struct rpmProblemObject_s rpmProblemObject; + +extern PyTypeObject rpmProblem_Type; + +#define rpmProblemObject_Check(v) ((v)->ob_type == &rpmProblem_Type) + +PyObject * rpmprob_Wrap(PyTypeObject *subtype, rpmProblem prob); + +PyObject *rpmps_AsList(rpmps ps); + +#endif diff --git a/python/rpmsmodule.c b/python/rpmsmodule.c new file mode 100644 index 0000000..e0b1b66 --- /dev/null +++ b/python/rpmsmodule.c @@ -0,0 +1,97 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmsign.h> + +#include "debug.h" + +static char rpms__doc__[] = +""; + +static PyObject * addSign(PyObject * self, PyObject * args, PyObject *kwds) +{ + const char *path = NULL; + const char *passPhrase = NULL; + char * kwlist[] = { "path", "passPhrase", "keyid", "hashalgo", NULL }; + struct rpmSignArgs sig, *sigp = NULL; + + memset(&sig, 0, sizeof(sig)); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|si", kwlist, + &path, &passPhrase, &sig.keyid, &sig.hashalgo)) + return NULL; + + if (sig.keyid || sig.hashalgo) + sigp = &sig; + + return PyBool_FromLong(rpmPkgSign(path, sigp, passPhrase) == 0); +} + +static PyObject * delSign(PyObject * self, PyObject * args, PyObject *kwds) +{ + const char *path = NULL; + char * kwlist[] = { "path", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &path)) + return NULL; + + return PyBool_FromLong(rpmPkgDelSign(path) == 0); +} + +/* + Do any common preliminary work before python 2 vs python 3 module creation: +*/ +static int prepareInitModule(void) +{ + return 1; +} + +static int initModule(PyObject *m) +{ + return 1; +} + +static PyMethodDef modMethods[] = { + { "addSign", (PyCFunction) addSign, METH_VARARGS|METH_KEYWORDS, NULL }, + { "delSign", (PyCFunction) delSign, METH_VARARGS|METH_KEYWORDS, NULL }, + { NULL }, +}; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_rpms", /* m_name */ + rpms__doc__, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; + +PyObject * PyInit__rpm(void); /* XXX eliminate gcc warning */ +PyObject * PyInit__rpm(void) +{ + PyObject *m; + + if (!prepareInitModule()) + return NULL; + m = PyModule_Create(&moduledef); + if (m == NULL || !initModule(m)) { + Py_XDECREF(m); + m = NULL; + } + return m; +} +#else +void init_rpms(void); /* XXX eliminate gcc warning */ +void init_rpms(void) +{ + PyObject *m; + + if (!prepareInitModule()) + return; + + m = Py_InitModule3("_rpms", modMethods, rpms__doc__); + if (m) initModule(m); +} +#endif diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h new file mode 100644 index 0000000..78d1fa8 --- /dev/null +++ b/python/rpmsystem-py.h @@ -0,0 +1,45 @@ +#ifndef H_SYSTEM_PYTHON +#define H_SYSTEM_PYTHON + +#if defined(__APPLE__) +#include <sys/types.h> +#endif + +#include <Python.h> +#include <structmember.h> + +#include "../system.h" + +#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) < 0x0205 +typedef ssize_t Py_ssize_t; +typedef Py_ssize_t (*lenfunc)(PyObject *); +#endif + +/* Compatibility macros for Python < 2.6 */ +#ifndef PyVarObject_HEAD_INIT +#define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, +#endif + +#ifndef Py_TYPE +#define Py_TYPE(o) ((o)->ob_type) +#endif + +#if ((PY_MAJOR_VERSION << 8) | (PY_MINOR_VERSION << 0)) < 0x0206 +#define PyBytes_Check PyString_Check +#define PyBytes_FromString PyString_FromString +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyBytes_Size PyString_Size +#define PyBytes_AsString PyString_AsString +#endif + +/* For Python 3, use the PyLong type throughout in place of PyInt */ +#if PY_MAJOR_VERSION >= 3 +#define PyInt_Check PyLong_Check +#define PyInt_AsLong PyLong_AsLong +#define PyInt_FromLong PyLong_FromLong +#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask +#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask +#endif + +#endif /* H_SYSTEM_PYTHON */ diff --git a/python/rpmtd-py.c b/python/rpmtd-py.c new file mode 100644 index 0000000..8232127 --- /dev/null +++ b/python/rpmtd-py.c @@ -0,0 +1,214 @@ +/** \ingroup py_c + * \file python/rpmtd-py.c + */ + +#include "rpmsystem-py.h" +#include <rpm/rpmtd.h> +#include <rpm/header.h> +#include "rpmtd-py.h" +#include "header-py.h" + +/* + * Convert single tag data item to python object of suitable type + */ +static PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass) +{ + PyObject *res = NULL; + + switch (tclass) { + case RPM_STRING_CLASS: + res = PyBytes_FromString(rpmtdGetString(td)); + break; + case RPM_NUMERIC_CLASS: + res = PyLong_FromLongLong(rpmtdGetNumber(td)); + break; + case RPM_BINARY_CLASS: + res = PyBytes_FromStringAndSize(td->data, td->count); + break; + default: + PyErr_SetString(PyExc_KeyError, "unknown data type"); + break; + } + return res; +} + +PyObject *rpmtd_AsPyobj(rpmtd td) +{ + PyObject *res = NULL; + int array = (rpmTagGetReturnType(td->tag) == RPM_ARRAY_RETURN_TYPE); + rpmTagClass tclass = rpmtdClass(td); + + if (!array && rpmtdCount(td) < 1) { + Py_RETURN_NONE; + } + + if (array) { + res = PyList_New(0); + while (rpmtdNext(td) >= 0) { + PyObject *item = rpmtd_ItemAsPyobj(td, tclass); + PyList_Append(res, item); + Py_DECREF(item); + } + } else { + res = rpmtd_ItemAsPyobj(td, tclass); + } + return res; +} + +#if 0 +struct rpmtdObject_s { + PyObject_HEAD + PyObject *md_dict; + struct rpmtd_s td; +}; + +/* string format should never fail but do regular repr just in case it does */ +static PyObject *rpmtd_str(rpmtdObject *s) +{ + PyObject *res = NULL; + char *str = rpmtdFormat(&(s->td), RPMTD_FORMAT_STRING, NULL); + if (str) { + res = PyBytes_FromString(str); + free(str); + } else { + res = PyObject_Repr((PyObject *)s); + } + return res; +} + +static PyObject *rpmtd_iternext(rpmtdObject *s) +{ + PyObject *next = NULL; + + if (rpmtdNext(&(s->td)) >= 0) { + Py_INCREF(s); + next = (PyObject*) s; + } + return next; +} + +static PyObject *rpmtd_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds) +{ + rpmtdObject *s = NULL; + Header h = NULL; + rpmTagVal tag; + int raw = 0; + int noext = 0; + headerGetFlags flags = (HEADERGET_EXT | HEADERGET_ALLOC); + char *kwlist[] = { "header", "tag", "raw", "noext", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|ii", kwlist, + hdrFromPyObject, &h, tagNumFromPyObject, &tag, + &raw, &noext)) + return NULL; + + if (raw) { + flags |= HEADERGET_RAW; + noext = 1; /* extensions with raw dont make sense */ + } + if (noext) flags &= ~HEADERGET_EXT; + + if ((s = (rpmtdObject *)subtype->tp_alloc(subtype, 0)) == NULL) + return NULL; + + headerGet(h, tag, &(s->td), flags); + + return (PyObject *) s; +} + +static void rpmtd_dealloc(rpmtdObject * s) +{ + rpmtdFreeData(&(s->td)); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static int rpmtd_length(rpmtdObject *s) +{ + return rpmtdCount(&(s->td)); +} + +static PyMappingMethods rpmtd_as_mapping = { + (lenfunc) rpmtd_length, /* mp_length */ +}; + +static PyMemberDef rpmtd_members[] = { + { "type", T_INT, offsetof(rpmtdObject, td.type), READONLY, NULL }, + { NULL } +}; + +static PyObject *rpmtd_get_tag(rpmtdObject *s, void *closure) +{ + return Py_BuildValue("i", rpmtdTag(&(s->td))); +} + +static int rpmtd_set_tag(rpmtdObject *s, PyObject *value, void *closure) +{ + rpmTagVal tag; + if (!tagNumFromPyObject(value, &tag)) return -1; + + if (!rpmtdSetTag(&(s->td), tag)) { + PyErr_SetString(PyExc_ValueError, "incompatible tag for data"); + return -1; + } + return 0; +} + +static PyGetSetDef rpmtd_getseters[] = { + { "tag", (getter)rpmtd_get_tag, (setter)rpmtd_set_tag, NULL }, + { NULL } +}; + +PyTypeObject rpmtd_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.td", /* tp_name */ + sizeof(rpmtdObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) rpmtd_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + &rpmtd_as_mapping, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc)rpmtd_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)rpmtd_iternext, /* tp_iternext */ + 0, /* tp_methods */ + rpmtd_members, /* tp_members */ + rpmtd_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + rpmtd_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +int rpmtdFromPyObject(PyObject *obj, rpmtd *td) +{ + if (rpmtdObject_Check(obj)) { + *td = &(((rpmtdObject *)obj)->td); + return 1; + } else { + PyErr_SetString(PyExc_TypeError, "rpm.td type expected"); + return 0; + } +} +#endif diff --git a/python/rpmtd-py.h b/python/rpmtd-py.h new file mode 100644 index 0000000..4c95e89 --- /dev/null +++ b/python/rpmtd-py.h @@ -0,0 +1,14 @@ +#ifndef H_RPMTD_PY +#define H_RPMTD_PY + +typedef struct rpmtdObject_s rpmtdObject; + +extern PyTypeObject rpmtd_Type; + +#define rpmtdObject_Check(v) ((v)->ob_type == &rpmtd_Type) + +PyObject * rpmtd_AsPyobj(rpmtd td); + +int rpmtdFromPyObject(PyObject *obj, rpmtd *td); + +#endif diff --git a/python/rpmte-py.c b/python/rpmte-py.c new file mode 100644 index 0000000..e017264 --- /dev/null +++ b/python/rpmte-py.c @@ -0,0 +1,302 @@ +#include "rpmsystem-py.h" + +#include "header-py.h" /* XXX tagNumFromPyObject */ +#include "rpmds-py.h" +#include "rpmfi-py.h" +#include "rpmte-py.h" +#include "rpmps-py.h" + +#include "debug.h" + + +/** \ingroup python + * \name Class: Rpmte + * \class Rpmte + * \brief An python rpm.te object represents an element of a transaction set. + * + * Elements of a transaction set are accessible after being added. Each + * element carries descriptive information about the added element as well + * as a file info set and dependency sets for each of the 4 types of dependency. + * + * The rpmte class contains the following methods: + * + * - te.Type() Return transaction element type (TR_ADDED|TR_REMOVED). + * - te.N() Return package name. + * - te.E() Return package epoch. + * - te.V() Return package version. + * - te.R() Return package release. + * - te.A() Return package architecture. + * - te.O() Return package operating system. + * - te.NEVR() Return package name-version-release. + * - te.Color() Return package color bits. + * - te.PkgFileSize() Return no. of bytes in package file (approx). + * - te.Parent() Return the parent element index. + * - te.Problems() Return problems associated with this element. + * - te.AddedKey() Return the added package index (TR_ADDED). + * - te.DependsOnKey() Return the package index for the added package (TR_REMOVED). + * - te.DBOffset() Return the Packages database instance number (TR_REMOVED) + * - te.Key() Return the associated opaque key, i.e. 2nd arg ts.addInstall(). + * - te.DS(tag) Return package dependency set. + * @param tag 'Providename', 'Requirename', 'Obsoletename', 'Conflictname' + * - te.FI(tag) Return package file info set. + * @param tag 'Basenames' + */ + +struct rpmteObject_s { + PyObject_HEAD + PyObject *md_dict; /*!< to look like PyModuleObject */ + rpmte te; +}; + +static PyObject * +rpmte_TEType(rpmteObject * s) +{ + return Py_BuildValue("i", rpmteType(s->te)); +} + +static PyObject * +rpmte_N(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteN(s->te)); +} + +static PyObject * +rpmte_E(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteE(s->te)); +} + +static PyObject * +rpmte_V(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteV(s->te)); +} + +static PyObject * +rpmte_R(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteR(s->te)); +} + +static PyObject * +rpmte_A(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteA(s->te)); +} + +static PyObject * +rpmte_O(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteO(s->te)); +} + +static PyObject * +rpmte_NEVR(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteNEVR(s->te)); +} + +static PyObject * +rpmte_NEVRA(rpmteObject * s) +{ + return Py_BuildValue("s", rpmteNEVRA(s->te)); +} + +static PyObject * +rpmte_Color(rpmteObject * s) +{ + return Py_BuildValue("i", rpmteColor(s->te)); +} + +static PyObject * +rpmte_PkgFileSize(rpmteObject * s) +{ + return Py_BuildValue("L", rpmtePkgFileSize(s->te)); +} + +static PyObject * +rpmte_Parent(rpmteObject * s) +{ + return Py_BuildValue("i", rpmteParent(s->te)); +} + +static PyObject * rpmte_Failed(rpmteObject * s) +{ + return Py_BuildValue("i", rpmteFailed(s->te)); +} + +static PyObject * rpmte_Problems(rpmteObject * s) +{ + rpmps ps = rpmteProblems(s->te); + PyObject *problems = rpmps_AsList(ps); + rpmpsFree(ps); + return problems; +} + +/* +static PyObject * +rpmte_DependsOnKey(rpmteObject * s) +{ + return Py_BuildValue("i", rpmteDependsOnKey(s->te)); +} +*/ + +static PyObject * +rpmte_DBOffset(rpmteObject * s) +{ + return Py_BuildValue("i", rpmteDBOffset(s->te)); +} + +static PyObject * +rpmte_Key(rpmteObject * s) +{ + PyObject * Key; + + /* XXX how to insure this is a PyObject??? */ + Key = (PyObject *) rpmteKey(s->te); + if (Key == NULL) + Key = Py_None; + Py_INCREF(Key); + return Key; +} + +static PyObject * +rpmte_DS(rpmteObject * s, PyObject * args, PyObject * kwds) +{ + rpmds ds; + rpmTagVal tag; + char * kwlist[] = {"tag", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:DS", kwlist, + tagNumFromPyObject, &tag)) + return NULL; + + ds = rpmteDS(s->te, tag); + if (ds == NULL) { + Py_RETURN_NONE; + } + return rpmds_Wrap(&rpmds_Type, rpmdsLink(ds)); +} + +static PyObject * +rpmte_FI(rpmteObject * s, PyObject * args, PyObject * kwds) +{ + rpmfi fi; + + fi = rpmteFI(s->te); + if (fi == NULL) { + Py_RETURN_NONE; + } + return rpmfi_Wrap(&rpmfi_Type, rpmfiLink(fi)); +} + +static struct PyMethodDef rpmte_methods[] = { + {"Type", (PyCFunction)rpmte_TEType, METH_NOARGS, +"te.Type() -> Type\n\ +- Return element type (rpm.TR_ADDED | rpm.TR_REMOVED).\n" }, + {"N", (PyCFunction)rpmte_N, METH_NOARGS, +"te.N() -> N\n\ +- Return element name.\n" }, + {"E", (PyCFunction)rpmte_E, METH_NOARGS, +"te.E() -> E\n\ +- Return element epoch.\n" }, + {"V", (PyCFunction)rpmte_V, METH_NOARGS, +"te.V() -> V\n\ +- Return element version.\n" }, + {"R", (PyCFunction)rpmte_R, METH_NOARGS, +"te.R() -> R\n\ +- Return element release.\n" }, + {"A", (PyCFunction)rpmte_A, METH_NOARGS, +"te.A() -> A\n\ +- Return element arch.\n" }, + {"O", (PyCFunction)rpmte_O, METH_NOARGS, +"te.O() -> O\n\ +- Return element os.\n" }, + {"NEVR", (PyCFunction)rpmte_NEVR, METH_NOARGS, +"te.NEVR() -> NEVR\n\ +- Return element name-[epoch:]version-release.\n" }, + {"NEVRA", (PyCFunction)rpmte_NEVRA, METH_NOARGS, +"te.NEVRA() -> NEVRA\n\ +- Return element name-[epoch:]version-release.arch\n" }, + {"Color",(PyCFunction)rpmte_Color, METH_NOARGS, + NULL}, + {"PkgFileSize",(PyCFunction)rpmte_PkgFileSize, METH_NOARGS, + NULL}, + {"Parent", (PyCFunction)rpmte_Parent, METH_NOARGS, + NULL}, + {"Problems",(PyCFunction)rpmte_Problems, METH_NOARGS, + NULL}, +/* {"DependsOnKey",(PyCFunction)rpmte_DependsOnKey, METH_NOARGS, + NULL}, */ + {"DBOffset",(PyCFunction)rpmte_DBOffset, METH_NOARGS, + NULL}, + {"Failed", (PyCFunction)rpmte_Failed, METH_NOARGS, + NULL}, + {"Key", (PyCFunction)rpmte_Key, METH_NOARGS, + NULL}, + {"DS", (PyCFunction)rpmte_DS, METH_VARARGS|METH_KEYWORDS, +"te.DS(TagN) -> DS\n\ +- Return the TagN dependency set (or None). TagN is one of\n\ + 'Providename', 'Requirename', 'Obsoletename', 'Conflictname'\n" }, + {"FI", (PyCFunction)rpmte_FI, METH_VARARGS|METH_KEYWORDS, +"te.FI(TagN) -> FI\n\ +- Return the TagN dependency set (or None). TagN must be 'Basenames'.\n" }, + {NULL, NULL} /* sentinel */ +}; + +/* ---------- */ + +static char rpmte_doc[] = +""; + +PyTypeObject rpmte_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.te", /* tp_name */ + sizeof(rpmteObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor)0, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmte_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rpmte_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * rpmte_Wrap(PyTypeObject *subtype, rpmte te) +{ + rpmteObject *s = (rpmteObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->te = te; + return (PyObject *) s; +} diff --git a/python/rpmte-py.h b/python/rpmte-py.h new file mode 100644 index 0000000..28bc0e3 --- /dev/null +++ b/python/rpmte-py.h @@ -0,0 +1,14 @@ +#ifndef H_RPMTE_PY +#define H_RPMTE_PY + +#include <rpm/rpmte.h> + +typedef struct rpmteObject_s rpmteObject; + +extern PyTypeObject rpmte_Type; + +#define rpmteObject_Check(v) ((v)->ob_type == &rpmte_Type) + +PyObject * rpmte_Wrap(PyTypeObject *subtype, rpmte te); + +#endif diff --git a/python/rpmts-py.c b/python/rpmts-py.c new file mode 100644 index 0000000..1e8a09a --- /dev/null +++ b/python/rpmts-py.c @@ -0,0 +1,904 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmlib.h> /* rpmReadPackageFile, headerCheck */ +#include <rpm/rpmtag.h> +#include <rpm/rpmpgp.h> +#include <rpm/rpmdb.h> +#include <rpm/rpmbuild.h> + +#include "header-py.h" +#include "rpmds-py.h" /* XXX for rpmdsNew */ +#include "rpmfd-py.h" +#include "rpmkeyring-py.h" +#include "rpmfi-py.h" /* XXX for rpmfiNew */ +#include "rpmmi-py.h" +#include "rpmii-py.h" +#include "rpmps-py.h" +#include "rpmte-py.h" + +#include "rpmts-py.h" + +#include "debug.h" + +/** \ingroup python + * \name Class: Rpmts + * \class Rpmts + * \brief A python rpm.ts object represents an RPM transaction set. + * + * The transaction set is the workhorse of RPM. It performs the + * installation and upgrade of packages. The rpm.ts object is + * instantiated by the TransactionSet function in the rpm module. + * + * The TransactionSet function takes two optional arguments. The first + * argument is the root path. The second is the verify signature disable flags, + * a set of the following bits: + * + * - rpm.RPMVSF_NOHDRCHK if set, don't check rpmdb headers + * - rpm.RPMVSF_NEEDPAYLOAD if not set, check header+payload (if possible) + * - rpm.RPMVSF_NOSHA1HEADER if set, don't check header SHA1 digest + * - rpm.RPMVSF_NODSAHEADER if set, don't check header DSA signature + * - rpm.RPMVSF_NOMD5 if set, don't check header+payload MD5 digest + * - rpm.RPMVSF_NODSA if set, don't check header+payload DSA signature + * - rpm.RPMVSF_NORSA if set, don't check header+payload RSA signature + * + * For convenience, there are the following masks: + * - rpm._RPMVSF_NODIGESTS if set, don't check digest(s). + * - rpm._RPMVSF_NOSIGNATURES if set, don't check signature(s). + * + * A rpm.ts object has the following methods: + * + * - addInstall(hdr,data,mode) Add an install element to a transaction set. + * @param hdr the header to be added + * @param data user data that will be passed to the transaction callback + * during transaction execution + * @param mode optional argument that specifies if this package should + * be installed ('i'), upgraded ('u'). + * + * - addErase(name) Add an erase element to a transaction set. + * @param name the package name to be erased + * + * - check() Perform a dependency check on the transaction set. After + * headers have been added to a transaction set, a dependency + * check can be performed to make sure that all package + * dependencies are satisfied. + * @return None If there are no unresolved dependencies + * Otherwise a list of complex tuples is returned, one tuple per + * unresolved dependency, with + * The format of the dependency tuple is: + * ((packageName, packageVersion, packageRelease), + * (reqName, reqVersion), + * needsFlags, + * suggestedPackage, + * sense) + * packageName, packageVersion, packageRelease are the name, + * version, and release of the package that has the unresolved + * dependency or conflict. + * The reqName and reqVersion are the name and version of the + * requirement or conflict. + * The needsFlags is a bitfield that describes the versioned + * nature of a requirement or conflict. The constants + * rpm.RPMSENSE_LESS, rpm.RPMSENSE_GREATER, and + * rpm.RPMSENSE_EQUAL can be logical ANDed with the needsFlags + * to get versioned dependency information. + * suggestedPackage is a tuple if the dependency check was aware + * of a package that solves this dependency problem when the + * dependency check was run. Packages that are added to the + * transaction set as "available" are examined during the + * dependency check as possible dependency solvers. The tuple + * contains two values, (header, suggestedName). These are set to + * the header of the suggested package and its name, respectively. + * If there is no known package to solve the dependency problem, + * suggestedPackage is None. + * The constants rpm.RPMDEP_SENSE_CONFLICTS and + * rpm.RPMDEP_SENSE_REQUIRES are set to show a dependency as a + * requirement or a conflict. + * + * - ts.order() Do a topological sort of added element relations. + * @return None + * + * - ts.setFlags(transFlags) Set transaction set flags. + * @param transFlags - bit(s) to controll transaction operations. The + * following values can be logically OR'ed together: + * - rpm.RPMTRANS_FLAG_TEST - test mode, do not modify the RPM + * database, change any files, or run any package scripts + * - rpm.RPMTRANS_FLAG_BUILD_PROBS - only build a list of + * problems encountered when attempting to run this transaction + * set + * - rpm.RPMTRANS_FLAG_NOSCRIPTS - do not execute package scripts + * - rpm.RPMTRANS_FLAG_JUSTDB - only make changes to the rpm + * database, do not modify files. + * - rpm.RPMTRANS_FLAG_NOTRIGGERS - do not run trigger scripts + * - rpm.RPMTRANS_FLAG_NODOCS - do not install files marked as %doc + * - rpm.RPMTRANS_FLAG_ALLFILES - create all files, even if a + * file is marked %config(missingok) and an upgrade is + * being performed. + * - rpm.RPMTRANS_FLAG_KEEPOBSOLETE - do not remove obsoleted + * packages. + * @return previous transFlags + * + * - ts.setProbFilter(ignoreSet) Set transaction set problem filter. + * @param problemSetFilter - control bit(s) to ignore classes of problems, + * a logical or of one or more of the following bit(s): + * - rpm.RPMPROB_FILTER_IGNOREOS - + * - rpm.RPMPROB_FILTER_IGNOREARCH - + * - rpm.RPMPROB_FILTER_REPLACEPKG - + * - rpm.RPMPROB_FILTER_FORCERELOCATE - + * - rpm.RPMPROB_FILTER_REPLACENEWFILES - + * - rpm.RPMPROB_FILTER_REPLACEOLDFILES - + * - rpm.RPMPROB_FILTER_OLDPACKAGE - + * - rpm.RPMPROB_FILTER_DISKSPACE - + * @return previous ignoreSet + * + * - ts.run(callback,data) Attempt to execute a transaction set. + * After the transaction set has been populated with install/upgrade or + * erase actions, the transaction set can be executed by invoking + * the ts.run() method. + */ + +struct rpmtsObject_s { + PyObject_HEAD + PyObject *md_dict; /*!< to look like PyModuleObject */ + rpmfdObject *scriptFd; + PyObject *keyList; + rpmts ts; + rpmtsi tsi; +}; + +struct rpmtsCallbackType_s { + PyObject * cb; + PyObject * data; + rpmtsObject * tso; + PyThreadState *_save; +}; + +RPM_GNUC_NORETURN +static void die(PyObject *cb) +{ + char *pyfn = NULL; + PyObject *r; + + if (PyErr_Occurred()) { + PyErr_Print(); + } + if ((r = PyObject_Repr(cb)) != NULL) { + pyfn = PyBytes_AsString(r); + } + fprintf(stderr, _("error: python callback %s failed, aborting!\n"), + pyfn ? pyfn : "???"); + rpmdbCheckTerminate(1); + exit(EXIT_FAILURE); +} + +static PyObject * +rpmts_AddInstall(rpmtsObject * s, PyObject * args) +{ + Header h = NULL; + PyObject * key; + int how = 0; + int rc; + + if (!PyArg_ParseTuple(args, "O&Oi:AddInstall", + hdrFromPyObject, &h, &key, &how)) + return NULL; + + rc = rpmtsAddInstallElement(s->ts, h, key, how, NULL); + if (key && rc == 0) { + PyList_Append(s->keyList, key); + } + return PyBool_FromLong((rc == 0)); +} + +static PyObject * +rpmts_AddErase(rpmtsObject * s, PyObject * args) +{ + Header h; + + if (!PyArg_ParseTuple(args, "O&:AddErase", hdrFromPyObject, &h)) + return NULL; + + return PyBool_FromLong(rpmtsAddEraseElement(s->ts, h, -1) == 0); +} + +static int +rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data) +{ + struct rpmtsCallbackType_s * cbInfo = (struct rpmtsCallbackType_s *) data; + PyObject * args, * result; + int res = 1; + + if (cbInfo->tso == NULL) return res; + if (cbInfo->cb == Py_None) return res; + + PyEval_RestoreThread(cbInfo->_save); + + args = Py_BuildValue("(Oissi)", cbInfo->tso, + rpmdsTagN(ds), rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds)); + result = PyEval_CallObject(cbInfo->cb, args); + Py_DECREF(args); + + if (!result) { + die(cbInfo->cb); + } else { + if (PyInt_Check(result)) + res = PyInt_AsLong(result); + Py_DECREF(result); + } + + cbInfo->_save = PyEval_SaveThread(); + + return res; +} + +static PyObject * +rpmts_Check(rpmtsObject * s, PyObject * args, PyObject * kwds) +{ + struct rpmtsCallbackType_s cbInfo; + int rc; + char * kwlist[] = {"callback", NULL}; + + memset(&cbInfo, 0, sizeof(cbInfo)); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:Check", kwlist, + &cbInfo.cb)) + return NULL; + + if (cbInfo.cb != NULL) { + if (!PyCallable_Check(cbInfo.cb)) { + PyErr_SetString(PyExc_TypeError, "expected a callable"); + return NULL; + } + rc = rpmtsSetSolveCallback(s->ts, rpmts_SolveCallback, (void *)&cbInfo); + } + + cbInfo.tso = s; + cbInfo._save = PyEval_SaveThread(); + + rc = rpmtsCheck(s->ts); + + PyEval_RestoreThread(cbInfo._save); + + return PyBool_FromLong((rc == 0)); +} + +static PyObject * +rpmts_Order(rpmtsObject * s) +{ + int rc; + + Py_BEGIN_ALLOW_THREADS + rc = rpmtsOrder(s->ts); + Py_END_ALLOW_THREADS + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmts_Clean(rpmtsObject * s) +{ + rpmtsClean(s->ts); + + Py_RETURN_NONE; +} + +static PyObject * +rpmts_OpenDB(rpmtsObject * s) +{ + int dbmode; + + dbmode = rpmtsGetDBMode(s->ts); + if (dbmode == -1) + dbmode = O_RDONLY; + + return Py_BuildValue("i", rpmtsOpenDB(s->ts, dbmode)); +} + +static PyObject * +rpmts_CloseDB(rpmtsObject * s) +{ + int rc; + + rc = rpmtsCloseDB(s->ts); + rpmtsSetDBMode(s->ts, -1); /* XXX disable lazy opens */ + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmts_InitDB(rpmtsObject * s) +{ + int rc; + + rc = rpmtsInitDB(s->ts, O_RDONLY); + if (rc == 0) + rc = rpmtsCloseDB(s->ts); + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmts_RebuildDB(rpmtsObject * s) +{ + int rc; + + Py_BEGIN_ALLOW_THREADS + rc = rpmtsRebuildDB(s->ts); + Py_END_ALLOW_THREADS + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmts_VerifyDB(rpmtsObject * s) +{ + int rc; + + Py_BEGIN_ALLOW_THREADS + rc = rpmtsVerifyDB(s->ts); + Py_END_ALLOW_THREADS + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmts_HdrFromFdno(rpmtsObject * s, PyObject *arg) +{ + PyObject *ho = NULL; + rpmfdObject *fdo = NULL; + Header h; + rpmRC rpmrc; + + if (!PyArg_Parse(arg, "O&:HdrFromFdno", rpmfdFromPyObject, &fdo)) + return NULL; + + Py_BEGIN_ALLOW_THREADS; + rpmrc = rpmReadPackageFile(s->ts, rpmfdGetFd(fdo), "rpmts_HdrFromFdno", &h); + Py_END_ALLOW_THREADS; + Py_XDECREF(fdo); + + if (rpmrc == RPMRC_OK) { + ho = hdr_Wrap(&hdr_Type, h); + h = headerFree(h); /* ref held by python object */ + } else { + Py_INCREF(Py_None); + ho = Py_None; + } + return Py_BuildValue("(iN)", rpmrc, ho); +} + +static PyObject * +rpmts_HdrCheck(rpmtsObject * s, PyObject *obj) +{ + PyObject * blob; + char * msg = NULL; + const void * uh; + int uc; + rpmRC rpmrc; + + if (!PyArg_Parse(obj, "S:HdrCheck", &blob)) + return NULL; + + uh = PyBytes_AsString(blob); + uc = PyBytes_Size(blob); + + Py_BEGIN_ALLOW_THREADS; + rpmrc = headerCheck(s->ts, uh, uc, &msg); + Py_END_ALLOW_THREADS; + + return Py_BuildValue("(is)", rpmrc, msg); +} + +static PyObject * +rpmts_PgpPrtPkts(rpmtsObject * s, PyObject * args, PyObject * kwds) +{ + PyObject * blob; + unsigned char * pkt; + unsigned int pktlen; + int rc; + char * kwlist[] = {"octets", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:PgpPrtPkts", kwlist, &blob)) + return NULL; + + pkt = (unsigned char *)PyBytes_AsString(blob); + pktlen = PyBytes_Size(blob); + + rc = pgpPrtPkts(pkt, pktlen, NULL, 1); + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmts_PgpImportPubkey(rpmtsObject * s, PyObject * args, PyObject * kwds) +{ + PyObject * blob; + unsigned char * pkt; + unsigned int pktlen; + int rc; + char * kwlist[] = {"pubkey", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:PgpImportPubkey", + kwlist, &blob)) + return NULL; + + pkt = (unsigned char *)PyBytes_AsString(blob); + pktlen = PyBytes_Size(blob); + + rc = rpmtsImportPubkey(s->ts, pkt, pktlen); + + return Py_BuildValue("i", rc); +} + +static PyObject *rpmts_setKeyring(rpmtsObject *s, PyObject *arg) +{ + rpmKeyring keyring = NULL; + if (arg == Py_None || rpmKeyringFromPyObject(arg, &keyring)) { + return PyBool_FromLong(rpmtsSetKeyring(s->ts, keyring) == 0); + } else { + PyErr_SetString(PyExc_TypeError, "rpm.keyring or None expected"); + return NULL; + } +} + +static PyObject *rpmts_getKeyring(rpmtsObject *s, PyObject *args, PyObject *kwds) +{ + rpmKeyring keyring = NULL; + int autoload = 1; + char * kwlist[] = { "autoload", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:getKeyring", + kwlist, &autoload)) + return NULL; + + keyring = rpmtsGetKeyring(s->ts, autoload); + if (keyring) { + return rpmKeyring_Wrap(&rpmKeyring_Type, keyring); + } else { + Py_RETURN_NONE; + } +} + +static void * +rpmtsCallback(const void * hd, const rpmCallbackType what, + const rpm_loff_t amount, const rpm_loff_t total, + const void * pkgKey, rpmCallbackData data) +{ + Header h = (Header) hd; + struct rpmtsCallbackType_s * cbInfo = data; + PyObject * pkgObj = (PyObject *) pkgKey; + PyObject * args, * result; + static FD_t fd; + + if (cbInfo->cb == Py_None) return NULL; + + /* Synthesize a python object for callback (if necessary). */ + if (pkgObj == NULL) { + if (h) { + pkgObj = Py_BuildValue("s", headerGetString(h, RPMTAG_NAME)); + } else { + pkgObj = Py_None; + Py_INCREF(pkgObj); + } + } else + Py_INCREF(pkgObj); + + PyEval_RestoreThread(cbInfo->_save); + + args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data); + result = PyEval_CallObject(cbInfo->cb, args); + Py_DECREF(args); + Py_DECREF(pkgObj); + + if (!result) { + die(cbInfo->cb); + } + + if (what == RPMCALLBACK_INST_OPEN_FILE) { + int fdno; + + if (!PyArg_Parse(result, "i", &fdno)) { + die(cbInfo->cb); + } + Py_DECREF(result); + cbInfo->_save = PyEval_SaveThread(); + + fd = fdDup(fdno); + fcntl(Fileno(fd), F_SETFD, FD_CLOEXEC); + + return fd; + } else + if (what == RPMCALLBACK_INST_CLOSE_FILE) { + Fclose (fd); + } + + Py_DECREF(result); + cbInfo->_save = PyEval_SaveThread(); + + return NULL; +} + +static PyObject * +rpmts_Problems(rpmtsObject * s) +{ + rpmps ps = rpmtsProblems(s->ts); + PyObject *problems = rpmps_AsList(ps); + rpmpsFree(ps); + return problems; +} + +static PyObject * +rpmts_Run(rpmtsObject * s, PyObject * args, PyObject * kwds) +{ + int rc; + struct rpmtsCallbackType_s cbInfo; + rpmprobFilterFlags ignoreSet; + char * kwlist[] = {"callback", "data", "ignoreSet", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOi:Run", kwlist, + &cbInfo.cb, &cbInfo.data, &ignoreSet)) + return NULL; + + cbInfo.tso = s; + cbInfo._save = PyEval_SaveThread(); + + if (cbInfo.cb != NULL) { + if (!PyCallable_Check(cbInfo.cb)) { + PyErr_SetString(PyExc_TypeError, "expected a callable"); + return NULL; + } + (void) rpmtsSetNotifyCallback(s->ts, rpmtsCallback, (void *) &cbInfo); + } + + rc = rpmtsRun(s->ts, NULL, ignoreSet); + + if (cbInfo.cb) + (void) rpmtsSetNotifyCallback(s->ts, NULL, NULL); + + PyEval_RestoreThread(cbInfo._save); + + return Py_BuildValue("i", rc); +} + +static PyObject * +rpmts_iternext(rpmtsObject * s) +{ + PyObject * result = NULL; + rpmte te; + + /* Reset iterator on 1st entry. */ + if (s->tsi == NULL) { + s->tsi = rpmtsiInit(s->ts); + if (s->tsi == NULL) + return NULL; + } + + te = rpmtsiNext(s->tsi, 0); + if (te != NULL) { + result = rpmte_Wrap(&rpmte_Type, te); + } else { + s->tsi = rpmtsiFree(s->tsi); + } + + return result; +} + +static PyObject * +rpmts_Match(rpmtsObject * s, PyObject * args, PyObject * kwds) +{ + PyObject *Key = NULL; + PyObject *str = NULL; + PyObject *mio = NULL; + char *key = NULL; +/* XXX lkey *must* be a 32 bit integer, int "works" on all known platforms. */ + int lkey = 0; + int len = 0; + rpmDbiTagVal tag = RPMDBI_PACKAGES; + char * kwlist[] = {"tagNumber", "key", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&O:Match", kwlist, + tagNumFromPyObject, &tag, &Key)) + return NULL; + + if (Key) { + if (PyInt_Check(Key)) { + lkey = PyInt_AsLong(Key); + key = (char *)&lkey; + len = sizeof(lkey); + } else if (utf8FromPyObject(Key, &str)) { + key = PyBytes_AsString(str); + len = PyBytes_Size(str); + } else { + PyErr_SetString(PyExc_TypeError, "unknown key type"); + return NULL; + } + /* One of the conversions above failed, exception is set already */ + if (PyErr_Occurred()) goto exit; + } + + /* XXX If not already opened, open the database O_RDONLY now. */ + /* XXX FIXME: lazy default rdonly open also done by rpmtsInitIterator(). */ + if (rpmtsGetRdb(s->ts) == NULL) { + int rc = rpmtsOpenDB(s->ts, O_RDONLY); + if (rc || rpmtsGetRdb(s->ts) == NULL) { + PyErr_SetString(pyrpmError, "rpmdb open failed"); + goto exit; + } + } + + mio = rpmmi_Wrap(&rpmmi_Type, rpmtsInitIterator(s->ts, tag, key, len), (PyObject*)s); + +exit: + Py_XDECREF(str); + return mio; +} +static PyObject * +rpmts_index(rpmtsObject * s, PyObject * args, PyObject * kwds) +{ + rpmDbiTagVal tag; + PyObject *mio = NULL; + char * kwlist[] = {"tag", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:Keys", kwlist, + tagNumFromPyObject, &tag)) + return NULL; + + /* XXX If not already opened, open the database O_RDONLY now. */ + if (rpmtsGetRdb(s->ts) == NULL) { + int rc = rpmtsOpenDB(s->ts, O_RDONLY); + if (rc || rpmtsGetRdb(s->ts) == NULL) { + PyErr_SetString(pyrpmError, "rpmdb open failed"); + goto exit; + } + } + + rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(s->ts), tag); + if (ii == NULL) { + PyErr_SetString(PyExc_KeyError, "No index for this tag"); + return NULL; + } + mio = rpmii_Wrap(&rpmii_Type, ii, (PyObject*)s); + +exit: + return mio; +} + +static struct PyMethodDef rpmts_methods[] = { + {"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS, + NULL }, + {"addErase", (PyCFunction) rpmts_AddErase, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"check", (PyCFunction) rpmts_Check, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"order", (PyCFunction) rpmts_Order, METH_NOARGS, + NULL }, + {"problems", (PyCFunction) rpmts_Problems, METH_NOARGS, +"ts.problems() -> ps\n\ +- Return current problem set.\n" }, + {"run", (PyCFunction) rpmts_Run, METH_VARARGS|METH_KEYWORDS, +"ts.run(callback, data) -> (problems)\n\ +- Run a transaction set, returning list of problems found.\n\ + Note: The callback may not be None.\n" }, + {"clean", (PyCFunction) rpmts_Clean, METH_NOARGS, + NULL }, + {"openDB", (PyCFunction) rpmts_OpenDB, METH_NOARGS, +"ts.openDB() -> None\n\ +- Open the default transaction rpmdb.\n\ + Note: The transaction rpmdb is lazily opened, so ts.openDB() is seldom needed.\n" }, + {"closeDB", (PyCFunction) rpmts_CloseDB, METH_NOARGS, +"ts.closeDB() -> None\n\ +- Close the default transaction rpmdb.\n\ + Note: ts.closeDB() disables lazy opens, and should hardly ever be used.\n" }, + {"initDB", (PyCFunction) rpmts_InitDB, METH_NOARGS, +"ts.initDB() -> None\n\ +- Initialize the default transaction rpmdb.\n\ + Note: ts.initDB() is seldom needed anymore.\n" }, + {"rebuildDB", (PyCFunction) rpmts_RebuildDB, METH_NOARGS, +"ts.rebuildDB() -> None\n\ +- Rebuild the default transaction rpmdb.\n" }, + {"verifyDB", (PyCFunction) rpmts_VerifyDB, METH_NOARGS, +"ts.verifyDB() -> None\n\ +- Verify the default transaction rpmdb.\n" }, + {"hdrFromFdno",(PyCFunction) rpmts_HdrFromFdno,METH_O, +"ts.hdrFromFdno(fdno) -> hdr\n\ +- Read a package header from a file descriptor.\n" }, + {"hdrCheck", (PyCFunction) rpmts_HdrCheck, METH_O, + NULL }, + {"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"pgpImportPubkey", (PyCFunction) rpmts_PgpImportPubkey, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"getKeyring", (PyCFunction) rpmts_getKeyring, METH_VARARGS|METH_KEYWORDS, + NULL }, + {"setKeyring", (PyCFunction) rpmts_setKeyring, METH_O, + NULL }, + {"dbMatch", (PyCFunction) rpmts_Match, METH_VARARGS|METH_KEYWORDS, +"ts.dbMatch([TagN, [key]]) -> mi\n\ +- Create a match iterator for the default transaction rpmdb.\n" }, + {"dbIndex", (PyCFunction) rpmts_index, METH_VARARGS|METH_KEYWORDS, +"ts.dbIndex(TagN) -> ii\n\ +- Create a key iterator for the default transaction rpmdb.\n" }, + {NULL, NULL} /* sentinel */ +}; + +static void rpmts_dealloc(rpmtsObject * s) +{ + + s->ts = rpmtsFree(s->ts); + Py_XDECREF(s->scriptFd); + Py_XDECREF(s->keyList); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static PyObject * rpmts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds) +{ + rpmtsObject * s = (rpmtsObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->ts = rpmtsCreate(); + s->scriptFd = NULL; + s->tsi = NULL; + s->keyList = PyList_New(0); + return (PyObject *) s; +} + +static int rpmts_init(rpmtsObject *s, PyObject *args, PyObject *kwds) +{ + char * rootDir = "/"; + rpmVSFlags vsflags = rpmExpandNumeric("%{?__vsflags}"); + char * kwlist[] = {"rootdir", "vsflags", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:rpmts_new", kwlist, + &rootDir, &vsflags)) + return -1; + + (void) rpmtsSetRootDir(s->ts, rootDir); + /* XXX: make this use common code with rpmts_SetVSFlags() to check the + * python objects */ + (void) rpmtsSetVSFlags(s->ts, vsflags); + + return 0; +} + +static PyObject *rpmts_get_tid(rpmtsObject *s, void *closure) +{ + return Py_BuildValue("i", rpmtsGetTid(s->ts)); +} + +static PyObject *rpmts_get_rootDir(rpmtsObject *s, void *closure) +{ + return Py_BuildValue("s", rpmtsRootDir(s->ts)); +} + +static int rpmts_set_scriptFd(rpmtsObject *s, PyObject *value, void *closure) +{ + rpmfdObject *fdo = NULL; + int rc = 0; + if (PyArg_Parse(value, "O&", rpmfdFromPyObject, &fdo)) { + Py_XDECREF(s->scriptFd); + s->scriptFd = fdo; + rpmtsSetScriptFd(s->ts, rpmfdGetFd(s->scriptFd)); + } else if (value == Py_None) { + Py_XDECREF(s->scriptFd); + s->scriptFd = NULL; + rpmtsSetScriptFd(s->ts, NULL); + } else { + rc = -1; + } + return rc; +} + +static PyObject *rpmts_get_color(rpmtsObject *s, void *closure) +{ + return Py_BuildValue("i", rpmtsColor(s->ts)); +} + +static PyObject *rpmts_get_prefcolor(rpmtsObject *s, void *closure) +{ + return Py_BuildValue("i", rpmtsPrefColor(s->ts)); +} + +static int rpmts_set_color(rpmtsObject *s, PyObject *value, void *closure) +{ + rpm_color_t color; + if (!PyArg_Parse(value, "i", &color)) return -1; + + /* TODO: validate the bits */ + rpmtsSetColor(s->ts, color); + return 0; +} + +static int rpmts_set_prefcolor(rpmtsObject *s, PyObject *value, void *closure) +{ + rpm_color_t color; + if (!PyArg_Parse(value, "i", &color)) return -1; + + /* TODO: validate the bits */ + rpmtsSetPrefColor(s->ts, color); + return 0; +} + +static int rpmts_set_flags(rpmtsObject *s, PyObject *value, void *closure) +{ + rpmtransFlags flags; + if (!PyArg_Parse(value, "i", &flags)) return -1; + + /* TODO: validate the bits */ + rpmtsSetFlags(s->ts, flags); + return 0; +} + +static int rpmts_set_vsflags(rpmtsObject *s, PyObject *value, void *closure) +{ + rpmVSFlags flags; + if (!PyArg_Parse(value, "i", &flags)) return -1; + + /* TODO: validate the bits */ + rpmtsSetVSFlags(s->ts, flags); + return 0; +} + +static PyObject *rpmts_get_flags(rpmtsObject *s, void *closure) +{ + return Py_BuildValue("i", rpmtsFlags(s->ts)); +} + +static PyObject *rpmts_get_vsflags(rpmtsObject *s, void *closure) +{ + return Py_BuildValue("i", rpmtsVSFlags(s->ts)); +} + +static char rpmts_doc[] = +""; + +static PyGetSetDef rpmts_getseters[] = { + /* only provide a setter until we have rpmfd wrappings */ + {"scriptFd", NULL, (setter)rpmts_set_scriptFd, NULL }, + {"tid", (getter)rpmts_get_tid, NULL, NULL }, + {"rootDir", (getter)rpmts_get_rootDir, NULL, NULL }, + {"_color", (getter)rpmts_get_color, (setter)rpmts_set_color, NULL}, + {"_prefcolor", (getter)rpmts_get_prefcolor, (setter)rpmts_set_prefcolor, NULL}, + {"_flags", (getter)rpmts_get_flags, (setter)rpmts_set_flags, NULL}, + {"_vsflags", (getter)rpmts_get_vsflags, (setter)rpmts_set_vsflags, NULL}, + { NULL } +}; + +PyTypeObject rpmts_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.ts", /* tp_name */ + sizeof(rpmtsObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) rpmts_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmts_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc) rpmts_iternext, /* tp_iternext */ + rpmts_methods, /* tp_methods */ + 0, /* tp_members */ + rpmts_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc) rpmts_init, /* tp_init */ + 0, /* tp_alloc */ + (newfunc) rpmts_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; diff --git a/python/rpmts-py.h b/python/rpmts-py.h new file mode 100644 index 0000000..e4fabfe --- /dev/null +++ b/python/rpmts-py.h @@ -0,0 +1,18 @@ +#ifndef H_RPMTS_PY +#define H_RPMTS_PY + +#include <rpm/rpmts.h> + +typedef struct rpmtsObject_s rpmtsObject; + +extern PyTypeObject rpmts_Type; + +#define rpmtsObject_Check(v) ((v)->ob_type == &rpmts_Type) + +/* XXX These names/constants have been removed from the rpmlib API. */ +enum { + RPMDEP_SENSE_REQUIRES, /*!< requirement not satisfied. */ + RPMDEP_SENSE_CONFLICTS /*!< conflict was found. */ +}; + +#endif diff --git a/python/spec-py.c b/python/spec-py.c new file mode 100644 index 0000000..a829539 --- /dev/null +++ b/python/spec-py.c @@ -0,0 +1,304 @@ +#include "rpmsystem-py.h" + +#include "header-py.h" +#include "spec-py.h" + +/** \ingroup python + * \name Class: Rpmspec + * \class Rpmspec + * \brief A python rpm.spec object represents an RPM spec file set. + * + * The spec file is at the heart of RPM's packaging building process. Similar + * in concept to a makefile, it contains information required by RPM to build + * the package, as well as instructions telling RPM how to build it. The spec + * file also dictates exactly what files are a part of the package, and where + * they should be installed. + * + * The rpm.spec object represents a parsed specfile to aid extraction of data. + * + * For example + * \code + * import rpm + * rpm.addMacro("_topdir","/path/to/topdir") + * s=rpm.spec("foo.spec") + * print s.prep() + * \endcode + * + * Macros set using add macro will be used allowing testing of conditional builds + * + */ + +/* Header objects are in another module, some hoop jumping required... */ +static PyObject *makeHeader(Header h) +{ + PyObject *rpmmod = PyImport_ImportModuleNoBlock("rpm"); + if (rpmmod == NULL) return NULL; + + PyObject *ptr = PyCObject_FromVoidPtr(h, NULL); + PyObject *hdr = PyObject_CallMethod(rpmmod, "hdr", "(O)", ptr); + Py_XDECREF(ptr); + Py_XDECREF(rpmmod); + return hdr; +} + +struct specPkgObject_s { + PyObject_HEAD + /*type specific fields */ + rpmSpecPkg pkg; +}; + +static char specPkg_doc[] = +""; + +static PyObject * specpkg_get_header(specPkgObject *s, void *closure) +{ + return makeHeader(rpmSpecPkgHeader(s->pkg)); +} + +static PyGetSetDef specpkg_getseters[] = { + { "header", (getter) specpkg_get_header, NULL, NULL }, + { NULL } /* sentinel */ +}; + +PyTypeObject specPkg_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.specpkg", /* tp_name */ + sizeof(specPkgObject), /* tp_size */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + specPkg_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + specpkg_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +struct specObject_s { + PyObject_HEAD + /*type specific fields */ + rpmSpec spec; +}; + +static void +spec_dealloc(specObject * s) +{ + if (s->spec) { + s->spec=rpmSpecFree(s->spec); + } + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static PyObject * getSection(rpmSpec spec, int section) +{ + const char *sect = rpmSpecGetSection(spec, section); + if (sect) { + return Py_BuildValue("s", sect); + } + Py_RETURN_NONE; +} + +static PyObject * +spec_get_prep(specObject * s, void *closure) +{ + return getSection(s->spec, RPMBUILD_PREP); +} + +static PyObject * +spec_get_build(specObject * s, void *closure) +{ + return getSection(s->spec, RPMBUILD_BUILD); +} + +static PyObject * spec_get_install(specObject * s, void *closure) +{ + return getSection(s->spec, RPMBUILD_INSTALL); +} + +static PyObject * spec_get_clean(specObject * s, void *closure) +{ + return getSection(s->spec, RPMBUILD_CLEAN); +} + +static PyObject * spec_get_sources(specObject *s, void *closure) +{ + PyObject *sourceList = PyList_New(0); + rpmSpecSrc source; + + rpmSpecSrcIter iter = rpmSpecSrcIterInit(s->spec); + while ((source = rpmSpecSrcIterNext(iter)) != NULL) { + PyObject *srcUrl = Py_BuildValue("(sii)", + rpmSpecSrcFilename(source, 1), + rpmSpecSrcNum(source), + rpmSpecSrcFlags(source)); + PyList_Append(sourceList, srcUrl); + Py_DECREF(srcUrl); + } + rpmSpecSrcIterFree(iter); + + return sourceList; + +} + +static PyObject * spec_get_packages(specObject *s, void *closure) +{ + rpmSpecPkg pkg; + PyObject *pkgList = PyList_New(0); + rpmSpecPkgIter iter = rpmSpecPkgIterInit(s->spec); + + while ((pkg = rpmSpecPkgIterNext(iter)) != NULL) { + PyObject *po = specPkg_Wrap(&specPkg_Type, pkg); + PyList_Append(pkgList, po); + Py_DECREF(po); + } + rpmSpecPkgIterFree(iter); + return pkgList; +} + +static PyObject * spec_get_source_header(specObject *s, void *closure) +{ + return makeHeader(rpmSpecSourceHeader(s->spec)); +} + +static char spec_doc[] = "RPM Spec file object"; + +static PyGetSetDef spec_getseters[] = { + {"sources", (getter) spec_get_sources, NULL, NULL }, + {"prep", (getter) spec_get_prep, NULL, NULL }, + {"build", (getter) spec_get_build, NULL, NULL }, + {"install", (getter) spec_get_install, NULL, NULL }, + {"clean", (getter) spec_get_clean, NULL, NULL }, + {"packages", (getter) spec_get_packages, NULL, NULL }, + {"sourceHeader", (getter) spec_get_source_header, NULL, NULL }, + {NULL} /* Sentinel */ +}; + +static PyObject *spec_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) +{ + char * kwlist[] = {"specfile", "flags", NULL}; + const char * specfile; + rpmSpec spec = NULL; + /* XXX This is a dumb default but anything else breaks compatibility... */ + rpmSpecFlags flags = (RPMSPEC_ANYARCH|RPMSPEC_FORCE); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i:spec_new", kwlist, + &specfile, &flags)) + return NULL; + + spec = rpmSpecParse(specfile, flags, NULL); + if (spec == NULL) { + PyErr_SetString(PyExc_ValueError, "can't parse specfile\n"); + return NULL; + } + + return spec_Wrap(subtype, spec); +} + +static PyObject * spec_doBuild(specObject *self, PyObject *args, PyObject *kwds) +{ + char * kwlist[] = { "buildAmount", "pkgFlags", NULL }; + struct rpmBuildArguments_s ba = { 0 }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i:spec_doBuild", + kwlist, &ba.buildAmount, &ba.pkgFlags)) + return NULL; + + return PyBool_FromLong(rpmSpecBuild(self->spec, &ba) == RPMRC_OK); +} + +static struct PyMethodDef spec_methods[] = { + { "_doBuild", (PyCFunction)spec_doBuild, METH_VARARGS|METH_KEYWORDS, NULL }, + { NULL, NULL } +}; + +PyTypeObject spec_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.spec", /*tp_name*/ + sizeof(specObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor) spec_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + spec_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + spec_methods, /* tp_methods */ + 0, /* tp_members */ + spec_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + spec_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * +spec_Wrap(PyTypeObject *subtype, rpmSpec spec) +{ + specObject * s = (specObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->spec = spec; + return (PyObject *) s; +} + +PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg) +{ + specPkgObject * s = (specPkgObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->pkg = pkg; + return (PyObject *) s; +} + diff --git a/python/spec-py.h b/python/spec-py.h new file mode 100644 index 0000000..558fbf2 --- /dev/null +++ b/python/spec-py.h @@ -0,0 +1,18 @@ +#ifndef RPMPYTHON_SPEC +#define RPMPYTHON_SPEC + +#include <rpm/rpmbuild.h> + +typedef struct specPkgObject_s specPkgObject; +typedef struct specObject_s specObject; + +extern PyTypeObject spec_Type; +extern PyTypeObject specPkg_Type; + +#define specObject_Check(v) ((v)->ob_type == &spec_Type) +#define specPkgObject_Check(v) ((v)->ob_type == &specPkg_Type) + +PyObject * spec_Wrap(PyTypeObject *subtype, rpmSpec spec); +PyObject * specPkg_Wrap(PyTypeObject *subtype, rpmSpecPkg pkg); + +#endif /* RPMPYTHON_SPEC */ |