#!/usr/bin/python import rpm import sys import os # Bare minimum callback for rpm to get by: it must be able to # open a file descriptor for a package file when requested to do so, # remember it and close it when asked to. It does not have to be # an object, but as it needs to remember state, object is a fairly # obvious solution to avoid global variables. class myCallback(object): def __init__(self): self._fd = None # The actual callback function. For opening and closing files, only 'event' # and 'key' are needed: event describes the callback reason, and # key is the object - whatever it was - that we passed to # ts.addInstall() as the second argument for this particular package. # Here it's an index to sys.argv where we can find the local path. def callback(self, event, amount, total, key, mydata): if event == rpm.RPMCALLBACK_INST_OPEN_FILE: path = sys.argv[key] print "Installing", path self._fd = os.open(path, os.O_RDONLY) return self._fd elif event == rpm.RPMCALLBACK_INST_CLOSE_FILE: self._fd = os.close(self._fd) if __name__ == '__main__': # A transaction set is needed for pretty much all rpm operations. ts = rpm.TransactionSet() # Add packages from the command line to our transaction for install. # Rpm grabs what it needs for its own purposes (dependency checking, # install ordering, file conflict resolution etc) from the header we # pass here, and discards it to conserve memory. The package is # reopened during the actual transaction, and this is what the # second argument is for: we need to hand the same file back to # rpm when its requested in the callback. Just for demonstration # purposes, we'll pass and index to sys.argv here: for idx in range(1, len(sys.argv)): fd = os.open(sys.argv[idx], os.O_RDONLY) hdr = ts.hdrFromFdno(fd) ts.addInstall(hdr, idx, 'u') os.close(fd) # Check for missing dependencies in the transaction set ts.check() if ts.problems(): rc = 1 else: # No problems, order the transaction and let rpm free memory # which is not needed from this point onwards. ts.order() ts.clean() # With the preliminaries out of the way, run the actual transaction. # The return codes from ts.run() are obscure, but None means # 'all went well', which is sufficient for this little demo. cb = myCallback() rc = (ts.run(cb.callback, None) != None) sys.exit(rc)