michael@13: #!@l_prefix@/lib/openpkg/bash michael@13: ## michael@13: ## rpmdb -- OpenPKG RPM Database Administration Utility michael@13: ## Copyright (c) 2000-2007 OpenPKG Foundation e.V. michael@13: ## Copyright (c) 2000-2007 Ralf S. Engelschall michael@13: ## michael@13: ## Permission to use, copy, modify, and distribute this software for michael@13: ## any purpose with or without fee is hereby granted, provided that michael@13: ## the above copyright notice and this permission notice appear in all michael@13: ## copies. michael@13: ## michael@13: ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED michael@13: ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF michael@13: ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. michael@13: ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR michael@13: ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@13: ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@13: ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF michael@13: ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND michael@13: ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, michael@13: ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT michael@13: ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF michael@13: ## SUCH DAMAGE. michael@13: ## michael@13: michael@13: # program information michael@13: progname="rpmdb" michael@13: michael@13: # configuration defaults michael@13: help="" michael@13: prefix="@l_prefix@" michael@13: dbpath="" michael@13: rpm="" michael@13: musr="@l_musr@" michael@13: mgrp="@l_mgrp@" michael@13: mode="" michael@13: force=no michael@13: verbose=2 michael@13: michael@13: ## michael@13: ## PARSE COMMAND LINE michael@13: ## michael@13: michael@13: # iterate over argument line michael@13: for opt michael@13: do michael@13: case $opt in michael@13: -*=*) arg=`echo "$opt" | sed 's/^[-_a-zA-Z0-9]*=//'` ;; michael@13: *) arg='' ;; michael@13: esac michael@13: case $opt in michael@13: -h|--help ) help="Usage" ;; michael@13: -B|--build ) mode=build ;; michael@13: -R|--rebuild ) mode=rebuild ;; michael@13: -C|--cleanup ) mode=cleanup ;; michael@13: -F|--fixate ) mode=fixate ;; michael@13: -L|--list ) mode=list ;; michael@13: -f|--force ) force=yes ;; michael@13: -q|--quiet ) verbose=0 ;; michael@13: -v|--verbose ) verbose=`expr $verbose + 1` ;; michael@13: --prefix=* ) prefix=$arg ;; michael@13: --dbpath=* ) dbpath=$arg ;; michael@13: --rpm=* ) rpm=$arg ;; michael@13: --musr=* ) musr=$arg ;; michael@13: --mgrp=* ) mgrp=$arg ;; michael@13: * ) help="Invalid option \`$opt'"; break ;; michael@13: esac michael@13: done michael@13: michael@13: # makre sure exactly one run-time mode is specified michael@13: if [ ".$mode" = . ]; then michael@13: help="No or invalid run-time mode specified" michael@13: fi michael@13: michael@13: # error or usage message michael@13: if [ ".$help" != . ]; then michael@13: if [ ".$help" != ".Usage" ]; then michael@13: echo "$progname:ERROR: $help" 1>&2 michael@13: fi michael@13: cat 1>&2 <&2 michael@13: exit 1 michael@13: } michael@13: michael@13: warning () { michael@13: echo "$progname:WARNING: $*" 1>&2 michael@13: } michael@13: michael@13: verbose () { michael@13: local level=$1 michael@13: shift michael@13: if [ $level -le $verbose ]; then michael@13: local lead="" michael@13: case "$level" in michael@13: 1 ) lead="" ;; michael@13: 2 ) lead="" ;; michael@13: 3 ) lead=" " ;; michael@13: * ) lead=" " ;; michael@13: esac michael@13: echo "$progname: $lead$*" 1>&2 michael@13: fi michael@13: } michael@13: michael@13: rpm () { michael@13: local opts="--dbpath `echo $dbpath | sed -e 's;/*$;;' -e 's;$;/;'`" michael@13: if [ ".$force" = .yes ]; then michael@13: opts="$opts --define '__dbi_private yes'" michael@13: fi michael@13: verbose 3 "run: $rpm $opts $@" michael@13: eval "$rpm $opts \"\$@\"" michael@13: } michael@13: michael@13: rpmdb_load () { michael@13: $prefix/lib/openpkg/rpmdb_load ${1+"$@"} michael@13: } michael@13: michael@13: rpmdb_dump () { michael@13: $prefix/lib/openpkg/rpmdb_dump ${1+"$@"} michael@13: } michael@13: michael@13: ## michael@13: ## RPM DATABASE OPERATIONS michael@13: ## michael@13: michael@13: db_wait () { michael@13: # wait until RPM has released the database in case we are called michael@13: # asynchronously to RPM (especially important when upgrading from michael@13: # RPM 4.0 where concurrent access is still not possible) michael@13: verbose 2 "waiting for RPM database to be available" michael@13: local i=0 michael@13: while [ $i -lt 10 ]; do michael@13: if $prefix/libexec/openpkg/rpm -q openpkg >/dev/null 2>&1; then michael@13: break michael@13: fi michael@13: sleep 1 michael@13: i=`expr $i + 1` michael@13: done michael@13: if [ $i -eq 10 ]; then michael@13: exit 1 michael@13: else michael@13: exit 0 michael@13: fi michael@13: } michael@13: michael@13: db_remove () { michael@13: # remove all known files michael@13: verbose 2 "removing (possibly existing) old RPM database DB files" michael@13: for dbfile in $dbfiles; do michael@13: eval `echo $dbfile | sed -e 's/^\(.*\):\(.*\)$/dbtype="\1"; dbfile="\2";/'` michael@13: verbose 3 "removing database file: $dbpath/$dbfile ($dbtype)" michael@13: rm -f $dbpath/$dbfile michael@13: done michael@13: } michael@13: michael@13: db_init () { michael@13: # perform official "initdb" operation michael@13: # (is mostly a no-operation in RPM 4.2, but anyway) michael@13: verbose 2 "creating new RPM database (built-in RPM procedure)" michael@13: rpm --initdb michael@13: michael@13: # perform some real RPM work, so more database files michael@13: # magically spring into existence michael@13: verbose 2 "operating on new RPM database" michael@13: rpm --import $prefix/etc/openpkg/openpkg.org.pgp || true michael@13: rpm -e gpg-pubkey-63c4cb9f-3c591eda --allmatches || true michael@13: michael@13: # perform official "rebuilddb" operation in the hope it michael@13: # creates even more database files now that we have some content michael@13: verbose 2 "rebuilding new RPM database (built-in RPM procedure)" michael@13: rpm --rebuilddb michael@13: } michael@13: michael@13: db_unbreak () { michael@13: # cleanup DB region files michael@13: verbose 2 "cleaning up RPM database DB region files" michael@13: for dbfile in $dbfiles; do michael@13: eval `echo $dbfile | sed -e 's/^\(.*\):\(.*\)$/dbtype="\1"; dbfile="\2";/'` michael@13: if [ ".$dbtype" = .region ]; then michael@13: verbose 3 "cleaning up DB file: $dbpath/$dbfile ($dbtype)" michael@13: rm -f $dbpath/$dbfile || true michael@13: touch $dbpath/$dbfile || true michael@13: fi michael@13: done michael@13: } michael@13: michael@13: db_extend () { michael@13: # make sure all RPM database DB files are present michael@13: verbose 2 "making sure RPM database contains all possible DB files" michael@13: for dbfile in $dbfiles; do michael@13: eval `echo $dbfile | sed -e 's/^\(.*\):\(.*\)$/dbtype="\1"; dbfile="\2";/'` michael@13: if [ ! -f $dbpath/$dbfile ]; then michael@13: verbose 3 "creating DB file: $dbpath/$dbfile ($dbtype)" michael@13: if [ ".$dbtype" = .hash -o ".$dbtype" = .btree ]; then michael@13: ( echo "VERSION=3" michael@13: echo "format=bytevalue" michael@13: echo "type=$dbtype" michael@13: echo "db_pagesize=16384" michael@13: echo "HEADER=END" michael@13: echo "DATA=END" michael@13: ) | rpmdb_load $dbpath/$dbfile || true michael@13: else michael@13: touch $dbpath/$dbfile || true michael@13: fi michael@13: fi michael@13: done michael@13: } michael@13: michael@13: db_reload () { michael@13: # rebuilding new from old RPM database DB files by dumping and michael@13: # reloading their entire content michael@13: verbose 2 "dumping and reloading RPM database DB file contents" michael@13: for dbfile in $dbfiles; do michael@13: eval `echo $dbfile | sed -e 's/^\(.*\):\(.*\)$/dbtype="\1"; dbfile="\2";/'` michael@13: verbose 3 "dumping and reloading DB file: $dbpath/$dbfile ($dbtype)" michael@13: if [ -f $dbpath/$dbfile ]; then michael@13: if [ ".$dbtype" = .hash -o ".$dbtype" = .btree ]; then michael@13: rpmdb_dump $dbpath/$dbfile |\ michael@13: rpmdb_load $dbpath/$dbfile.new michael@13: rm -f $dbpath/$dbfile michael@13: mv $dbpath/$dbfile.new $dbpath/$dbfile michael@13: else michael@13: rm -f $dbpath/$dbfile || true michael@13: touch $dbpath/$dbfile || true michael@13: fi michael@13: fi michael@13: done michael@13: } michael@13: michael@13: db_rebuild () { michael@13: # perform official "rebuilddb" operation michael@13: verbose 2 "rebuilding RPM database (built-in RPM procedure)" michael@13: rpm --rebuilddb michael@13: } michael@13: michael@13: db_operate () { michael@13: # perform some read/write operation on RPM database michael@13: # (we have no package available, but removing and reimporting michael@13: # the OpenPKG OpenPGP keys is a harmless thing and always possible) michael@13: verbose 2 "performing read/write operation on RPM database" michael@13: for spec in \ michael@13: openpkg.org.pgp:gpg-pubkey-63c4cb9f-3c591eda \ michael@13: openpkg.com.pgp:gpg-pubkey-61b7ae34-4544a6af \ michael@13: openpkg.net.pgp:gpg-pubkey-52197903-4544a74d \ michael@13: ; do michael@13: eval `echo "$spec" | sed -e 's/^\(.*\):\(.*\)$/file="\1"; package="\2"/'` michael@13: rpm -q $package >/dev/null 2>&1 && rpm -e $package --allmatches || true michael@13: rpm -q $package >/dev/null 2>&1 || rpm --import $prefix/etc/openpkg/$file || true michael@13: done michael@13: rpm -qa >/dev/null 2>&1 michael@13: } michael@13: michael@13: db_fixate () { michael@13: # fix ownership and permissions of (especially newly created) michael@13: # RPM database files to make sure they are consistent michael@13: verbose 2 "making sure RPM database files have consistent attributes" michael@13: for dbfile in $dbfiles; do michael@13: eval `echo $dbfile | sed -e 's/^\(.*\):\(.*\)$/dbtype="\1"; dbfile="\2";/'` michael@13: verbose 3 "fixating DB file: $dbpath/$dbfile ($dbtype)" michael@13: chown $musr:$mgrp $dbpath/$dbfile 2>/dev/null || true michael@13: chmod 644 $dbpath/$dbfile 2>/dev/null || true michael@13: done michael@13: } michael@13: michael@13: db_list () { michael@13: # list all database files michael@13: for dbfile in $dbfiles; do michael@13: eval `echo $dbfile | sed -e 's/^\(.*\):\(.*\)$/dbtype="\1"; dbfile="\2";/'` michael@13: if [ $verbose -eq 0 ]; then michael@13: echo "$dbfile" michael@13: elif [ $verbose -eq 1 ]; then michael@13: echo "$dbpath/$dbfile" michael@13: elif [ $verbose -ge 2 ]; then michael@13: echo "$dbpath/$dbfile ($dbtype)" michael@13: fi michael@13: done michael@13: } michael@13: michael@13: ## michael@13: ## ENVIRONMENT CONSISTENCY CHECKS michael@13: ## michael@13: michael@13: # sanity check OpenPKG instance michael@13: if [ ".$prefix" = . ]; then michael@13: error "OpenPKG instance directory is empty" michael@13: fi michael@13: if [ ! -d $prefix ]; then michael@13: error "OpenPKG instance directory \"$prefix\" not found" michael@13: fi michael@13: if [ ! -x $prefix/bin/openpkg ]; then michael@13: error "OpenPKG instance directory \"$prefix\" not valid" michael@13: fi michael@13: michael@13: # sanity check OpenPKG RPM database michael@13: if [ ".$dbpath" = . ]; then michael@13: error "OpenPKG RPM database directory is empty" michael@13: fi michael@13: if [ ! -d $dbpath ]; then michael@13: error "OpenPKG RPM database directory \"$dbpath\" not found" michael@13: fi michael@13: if [ ! -w $dbpath ]; then michael@13: error "OpenPKG RPM database directory \"$dbpath\" not writable" michael@13: fi michael@13: michael@13: ## michael@13: ## DISPATCH INTO COMMANDS michael@13: ## michael@13: michael@13: case "$mode" in michael@13: build ) michael@13: verbose 1 "BUILDING NEW RPM DATABASE FROM SCRATCH ($dbpath)" michael@13: db_remove michael@13: db_init michael@13: db_extend michael@13: db_rebuild michael@13: db_fixate michael@13: db_operate michael@13: ;; michael@13: michael@13: rebuild ) michael@13: verbose 1 "REBUILDING NEW FROM OLD RPM DATABASE ($dbpath)" michael@13: db_unbreak michael@13: db_extend michael@13: db_reload michael@13: db_rebuild michael@13: db_fixate michael@13: db_operate michael@13: ;; michael@13: michael@13: cleanup ) michael@13: verbose 1 "CLEANING UP EXISTING RPM DATABASE ($dbpath)" michael@13: db_unbreak michael@13: db_extend michael@13: db_rebuild michael@13: db_fixate michael@13: db_operate michael@13: ;; michael@13: michael@13: fixate ) michael@13: verbose 1 "FIXATING EXISTING RPM DATABASE ($dbpath)" michael@13: db_extend michael@13: db_fixate michael@13: db_operate michael@13: ;; michael@13: michael@13: list ) michael@13: db_list michael@13: ;; michael@13: esac michael@13: michael@13: exit 0 michael@13: