rpm プログラミング with python を読み砕く : 2

引用元ドキュメントから自分勝手に要点のみを抜粋

パッケージファイルを読み込む

Python API は、インストールされた RPM パッケージの処理に加えて、RPM パッケージファイルを処理するメソッドを含みます。これらの大半のメソッドはヘッダオブジェクトを要求します。

  • パッケージファイルからヘッダを読み込む

Python APIRPM パッケージのヘッダオブジェクトを読み込む便利な方法を提供します。hdrFromFdno() メソッドは、ファイルディスクリプタから RPM ヘッダを読み込みます。

  • 注意

hdrFromFdno() メソッドは、ハイレベルな Python ファイルオブジェクトではなく、ローレベルな Python のファイルディスクリプタを使用します。以下に、ファイルをオープンして、RPM ヘッダを読み込み、ファイルをクローズする例を示します。また、パッケージファイル内で問題を検出したら例外を発生させます。

#!/bin/env python
# -*- coding: utf-8 -*-

import rpm, sys, os

def readRpmHeader(ts, filename):
    h = None
    fd = os.open(filename, os.O_RDONLY)
    
    try:
        h = ts.hdrFromFdno(fd)
    except rpm.error, e:
        if str(e) == "パブリックキーが無効です":
            print str(e)
        if str(e) == "パブリックキーが信用できません":
            print str(e)
        if str(e) == "パッケージヘッダの読み込みに失敗しました":
            print str(e)
        h = None
    
    os.close(fd)
    return h

def main():
    ts = rpm.TransactionSet()
    h = readRpmHeader(ts, sys.argv[1])
    if h != None:
        for i in xrange(1000,1006):
            print i, h[i]

if __name__ == '__main__':
    main()

実行結果。

# ./readrpmheader.py python-2.5.1-2m.mo4.i686.rpm
1000 python
1001 2.5.1
1002 2m.mo4
1003 None
1004 An interpreted, interactive, object-oriented programming language.
1005 Python is an interpreted, interactive, object-oriented programming
language often compared to Tcl, Perl, Scheme or Java. Python includes
modules, classes, exceptions, very high level dynamic data types and
dynamic typing. Python supports interfaces to many system calls and
libraries, as well as to various windowing systems (X11, Motif, Tk,
Mac and MFC).

Programmers can write new built-in modules for Python in C or C++.
Python can be used as an extension language for applications that need
a programmable interface. This package contains most of the standard
Python modules, as well as modules for interfacing to the Tix widget
set for Tk and RPM.

Note that documentation for Python is provided in the python-docs
package.
  • 検証フラグをセットする

RPM4.1 では、自動的にパッケージファイルを検証します。それが古いバージョンであったり、適切な署名がされていなかったりすると、不具合を引き起こすこともあります。ほとんどのケースでは、パッケージファイルの信頼性を確保できるので自動検証にはメリットがあります。しかしながら、デフォルトの動作を変更するためにトランザクション上で setVSFlags を呼ぶ出すことも可能です。

例えば、適切な署名を持っていない古いパッケージならば、以下のようにしてチェックを無視することができます。

# DSA署名を検証しないようにセットする
ts.setVSFlags(rpm.RPMVSF_NODSA)

以下のリストは、トランザクションセットへ渡せるフラグです。これらのフラグはビットマスクです。1つないし複数のフラグを同時にセットできますが、バイナリで操作しなければなりません。Pythonやキーワードを使わずに、バイナリ操作に "|" を使ってください。

フラグ 概要
rpm.RPMVSF_NEEDPAYLOAD ペイロードの最初のファイルハンドラ位置を委任する
rpm.RPMVSF_NOHDRCHK RPMデータベースヘッダをチェックしない
rpm.RPMVSF_NODSA ヘッダとペイロードのDSA署名をチェックしない
rpm.RPMVSF_NODSAHEADER ヘッダのDSA署名をチェックしない
rpm.RPMVSF_NOMD5 ヘッダとペイロードMD5ダイジェストをチェックしない
rpm.RPMVSF_NORSA ヘッダとペイロードRSA署名をチェックしない
rpm.RPMVSF_NOSHA1HEADER ヘッダのSHA1署名をチェックしない
rpm._RPMVSF_NODIGESTS ダイジェストをチェックしない
rpm._RPMVSF_NOSIGNATURES 署名をチェックしない

全てのチェックを無効にするには setVSFlags に -1 を渡します。

ts.setVSFlags(-1)
依存関係の比較

2つのパッケージ間の依存関係を比較する依存関係セットがあります。一般的な使い方として、インストールされているパッケージのバージョンよりも新しいバージョンのパッケージファイルであるか、パッケージファイルを比較します。

ヘッダのデフォルト依存関係セットを取得するために、ヘッダオブジェクトのdsOfHeaderを呼び出すことができます。2つのヘッダからの依存関係セットを用意して、以下のようにしてどちらが新しいかを確認できます。

#!/bin/env python
# -*- coding: utf-8 -*-

import rpm, os, sys

def readRpmHeader(ts, filename):
    fd = os.open(filename, os.O_RDONLY)
    h = ts.hdrFromFdno(fd)
    os.close(fd)
    return h

def main():
    ts = rpm.TransactionSet()
    h = readRpmHeader(ts, sys.argv[1])
    pkg_ds = h.dsOfHeader()
    inst_h = ''
    
    for inst_h in ts.dbMatch('name', h['name']):
        inst_ds = inst_h.dsOfHeader()
        if pkg_ds.EVR() >= inst_ds.EVR():
            print "パッケージファイルは同じ又は新しいのでアップグレード可能です"
        else:
            print "パッケージファイルはインストールされたものより古いです"
    
    if not inst_h:
        print "パッケージファイルはインストールされていないのでインストール可能です"

if __name__ == '__main__':
    main()

実行結果。

# rpm -q python wxPython
python-2.5.1-2m.mo4
パッケージ wxPython はインストールされていません。

# ./vercompare.py python-2.5.1-2m.mo4.i686.rpm
パッケージファイルは同じ又は新しいのでアップグレード可能です
# ./vercompare.py python-2.4.2-11m.i686.rpm
パッケージファイルはインストールされたものより古いです
# ./vercompare.py wxPython-2.6.3.3-2m.mo4.i686.rpm
パッケージファイルはインストールされていないのでインストール可能です
  • クロスリファレンス

このスクリプトコマンドラインからファイル名を取得して、パッケージのヘッダをロードし、RPM データベース内にインストールされている全てのパッケージ内から同じ名前を探します。各々のマッチした名前に対して、このスクリプトはどちらが新しいかを比較します。