From f54a888a1facfd8f086d6414260be5f1b991a66b Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Tue, 25 Nov 2003 02:02:36 +0000 Subject: Imported from pacman-2.7.tar.gz --- ChangeLog | 9 ++ Makefile.in | 2 +- README | 2 +- doc/makepkg.8.in | 41 +++++-- doc/pacman.8.in | 3 + etc/makepkg.conf | 5 +- etc/pacman.conf | 2 +- scripts/gensync | 43 ++++++- scripts/makepkg | 174 ++++++++++++++++---------- scripts/makeworld | 12 +- src/db.c | 31 +++-- src/db.h | 2 +- src/list.c | 1 + src/package.c | 5 + src/package.h | 9 ++ src/pacman.c | 357 ++++++++++++++++++++++++++++++++++++++---------------- src/pacman.h | 4 +- 17 files changed, 500 insertions(+), 202 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02afc1dd..840691cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ VERSION DESCRIPTION ----------------------------------------------------------------------------- +2.7 - Added build-time dependencies to makepkg (Jason Chu) + - Added md5sum integrity checking to packages in --sync + mode (Aurelien Foret) + - Memory leak fixes (Aurelien Foret) + - Added CARCH variable to makepkg.conf for use in PKGBUILDs + - Added LogFile option for direct-to-file logging + - Added -Qii handling to show modified config files + - Allow --sync targets to specify an explicit repository to + sync from (eg, pacman -S current/patch) 2.6.4 - Altered pacman_upgrade() to allow a package to replace itself 2.6.3 - A couple memory fixes in the new replaces code 2.6.2 - Fixed a memory cleanup bug diff --git a/Makefile.in b/Makefile.in index 7eda945f..987d4e1b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -34,7 +34,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ -PACVER = 2.6.4 +PACVER = 2.7 TOPDIR = @srcdir@ SRCDIR = $(TOPDIR)/src/ diff --git a/README b/README index d9b0b1c5..2aa5057a 100644 --- a/README +++ b/README @@ -51,7 +51,7 @@ it helps. COPYRIGHT: ---------- -pacman is Copyright (c) 2002 Judd Vinet and is +pacman is Copyright (c) 2002-2003 Judd Vinet and is licensed through the GNU General Public License (see COPYING). pacman uses "libtar", a library for reading/writing tar-files. This diff --git a/doc/makepkg.8.in b/doc/makepkg.8.in index 03c96a06..9ade54b0 100644 --- a/doc/makepkg.8.in +++ b/doc/makepkg.8.in @@ -1,4 +1,4 @@ -.TH makepkg 8 "September 01, 2003" "makepkg #VERSION#" "" +.TH makepkg 8 "November 22, 2003" "makepkg #VERSION#" "" .SH NAME makepkg \- package build utility .SH SYNOPSIS @@ -36,7 +36,8 @@ pkgrel=1 pkgdesc="Utilities for inserting and removing modules from the linux kernel" url="http://www.kernel.org" backup=(etc/modules.conf) -depends=('mawk' 'bash' 'glibc' 'zlib') +makedepends=('bash' 'mawk') +depends=('glibc' 'zlib') source=(ftp://ftp.kernel.org/pub/linux/utils/kernel/$pkgname/v2.4/$pkgname-$pkgver.tar.bz2 \\ modules.conf) md5sums=('2c0cca3ef6330a187c6ef4fe41ecaa4d' \\ @@ -64,9 +65,11 @@ The line with \fIbackup=\fP specifies files that should be treated specially when removing or upgrading packages. See \fBHANDLING CONFIG FILES\fP in the \fIpacman\fP manpage for more information on this. -The seventh line lists the dependencies for this package. In order to build/run -the package, all dependencies must be satisifed first. makepkg will check this -before attempting to build the package. +Lines 7 and 8 list the dependencies for this package. The \fIdepends\fP array +specifies the run-time dependencies and \fImakedepends\fP specifies the build-time +dependencies. In order to run the package, \fIdepends\fP must be satisfied. To +build the package, \fBall\fP dependencies must be satisifed first. makepkg +will check this before attempting to build the package. The \fIsource\fP array tells makepkg which files to download/extract before compiling begins. The \fImd5sums\fP array provides md5sums for each of these files. These @@ -97,6 +100,8 @@ make prefix=$startdir/pkg/usr install .fi .RE Notice that the "/usr" portion should be present with "prefix", but not "DESTDIR". +"DESTDIR" is the favorable option to use, but not all Makefiles support it. Use +"prefix" only when "DESTDIR" is unavailable. Once the package is successfully installed into the package root, \fImakepkg\fP will remove some directories (as per Arch Linux package guidelines; if you use @@ -214,6 +219,15 @@ file, unless they have a fully-qualified URL. Then if the source file does not already exist in /var/cache/pacman/src, the file is downloaded by wget. +.TP +.B md5sums \fI(array)\fP +If this field is present, it should contain an MD5 hash for every source file +specified in the \fIsource\fP array (in the same order). makepkg will use +this to verify source file integrity during subsequent builds. To easily +generate md5sums, first build using the PKGBUILD then run +\fBmakepkg -g >>PKGBILD\fP. Then you can edit the PKGBUILD and move the +\fImd5sums\fP line from the bottom to an appropriate location. + .TP .B groups \fI(array)\fP This is an array of symbolic names that represent groups of packages, allowing @@ -237,6 +251,11 @@ package name. They can also include a version requirement of the form (greater than equal to), \fB<=\fP (less than or equal to), or \fB=\fP (equal to). See the PKGBUILD example above for an example of the \fIdepends\fP directive. +.TP +.B makedepends \fI(array)\fP +An array of packages that this package depends on to build (ie, not required +to run). Packages in this list should follow the same format as \fIdepends\fP. + .TP .B conflicts \fI(array)\fP An array of packages that will conflict with this package (ie, they cannot both @@ -260,8 +279,8 @@ to the differing package names. \fIreplaces\fP handles this. .SH MAKEPKG OPTIONS .TP .B "\-b, \-\-builddeps" -Build missing dependencies from source. When makepkg finds missing -dependencies, it will look for the dependencies' PKGBUILD files under +Build missing dependencies from source. When makepkg finds missing build-time or +run-time dependencies, it will look for the dependencies' PKGBUILD files under $ABSROOT (set in your /etc/makepkg.conf). If it finds them it will run another copy of makepkg to build and install the missing dependencies. The child makepkg calls will be made with the \fB-b\fP and \fB-i\fP options. @@ -299,9 +318,13 @@ Do not strip binaries and libraries. .B "\-p " Read the package script \fI\fP instead of the default (\fIPKGBUILD\fP). .TP +.B "\-r, \-\-rmdeps" +Upon successful build, remove any dependencies installed by makepkg/pacman during +dependency auto-resolution (using \fB-b\fP or \fB-s\fP). +.TP .B "\-s, \-\-syncdeps" -Install missing dependencies using pacman. When makepkg finds missing -dependencies, it will run pacman to try and resolve them. If successful, +Install missing dependencies using pacman. When makepkg finds missing build-time +or run-time dependencies, it will run pacman to try and resolve them. If successful, pacman will download the missing packages from a package repository and install them for you. .TP diff --git a/doc/pacman.8.in b/doc/pacman.8.in index 778a5974..859f0b4b 100644 --- a/doc/pacman.8.in +++ b/doc/pacman.8.in @@ -211,6 +211,9 @@ install/upgrade. \fINote:\fP do not include the leading slash when specifying f .B "UseSyslog" Log action messages through syslog(). This will insert pacman log entries into your /var/log/messages or equivalent. +.TP +.B "LogFile = /path/to/file" +Log actions directly to a file, usually /var/log/pacman.log. .SH CONFIG: REPOSITORIES Each repository section defines a section name and at least one location where the packages diff --git a/etc/makepkg.conf b/etc/makepkg.conf index 0a2a7548..4c8f9969 100644 --- a/etc/makepkg.conf +++ b/etc/makepkg.conf @@ -7,14 +7,15 @@ export FTPAGENT="/usr/bin/wget --continue --passive-ftp --tries=3 --waitretry=3" #export FTPAGENT="/usr/bin/snarf" #export FTPAGENT="/usr/bin/lftpget -c" +export CARCH="i686" +export CHOST="i686-pc-linux-gnu" + # Pentium Pro/Pentium II/Pentium III+/Pentium 4/Athlon exclusive (binaries # will use the P6 instruction set and only run on P6+ systems) -export CHOST="i686-pc-linux-gnu" export CFLAGS="-march=i686 -O2 -pipe" export CXXFLAGS="-march=i686 -O2 -pipe" # Pentium Pro/Pentium II/Pentium III+/Pentium 4/Athlon optimized (but binaries # will run on any x86 system) -#export CHOST="i686-pc-linux-gnu" #export CFLAGS="-mcpu=i686 -O2 -pipe" #export CXXFLAGS="-mcpu=i686 -O2 -pipe" diff --git a/etc/pacman.conf b/etc/pacman.conf index 4e37d572..c2592b29 100644 --- a/etc/pacman.conf +++ b/etc/pacman.conf @@ -8,7 +8,7 @@ # GENERAL OPTIONS # [options] -UseSyslog +LogFile = /var/log/pacman.log NoUpgrade = etc/passwd etc/group etc/shadow NoUpgrade = etc/fstab etc/raidtab NoUpgrade = etc/rc.conf etc/rc.local diff --git a/scripts/gensync b/scripts/gensync index 045c4f38..5a0b7eda 100755 --- a/scripts/gensync +++ b/scripts/gensync @@ -20,7 +20,7 @@ # USA. # -myver='2.6.4' +myver='2.7' usage() { echo "gensync $myver" @@ -42,6 +42,22 @@ usage() { exit 0 } +get_md5checksum() +{ + source $1 || return 1 + if [ "$pkgdir" != "" ]; then + pkgfile="$pkgdir/$pkgname-$pkgver-$pkgrel.pkg.tar.gz" + else + pkgfile="$destdir/$pkgname-$pkgver-$pkgrel.pkg.tar.gz" + fi + if [ -f $pkgfile ]; then + md5line=`md5sum $pkgfile` + [ ! -z "$md5line" ] && pkgmd5sum=${md5line% *} + echo $pkgmd5sum + fi + return 0 +} + db_write_entry() { unset pkgname pkgver pkgrel pkgdesc @@ -61,6 +77,11 @@ db_write_entry() echo "%DESC%" >>desc echo "$pkgdesc" >>desc echo "" >>desc + if [ ! -z $pkgmd5sum ]; then + echo "%MD5SUM%" >>desc + echo "$pkgmd5sum" >>desc + echo "" >>desc + fi if [ ${#groups[*]} -gt 0 ]; then echo "%GROUPS%" >>desc for it in "${groups[@]}"; do @@ -111,11 +132,14 @@ if [ "$1" = "-h" -o "$1" = "--help" ]; then fi d=`dirname $1` -rootdir=`cd $d && pwd` -rootdir="$rootdir/`basename $1`" +rootdir=`cd $d && pwd`/`basename $1` d=`dirname $2` -destfile=`cd $d && pwd` -destfile="$destfile/`basename $2`" +destdir=`cd $d && pwd` +destfile="$destdir/`basename $2`" +pkgdir= +if [ "$3" != "" ]; then + pkgdir=$3 +fi rm -rf /tmp/.gensync || exit 1 mkdir -p /tmp/.gensync || exit 1 @@ -126,9 +150,16 @@ if [ ! -d $rootdir ]; then exit 1 fi -echo "gensync: building database entries..." >&2 +echo "gensync: building database entries, generating md5sums..." >&2 +cd `dirname $2` #for category in `find $rootdir/* -type d -maxdepth 0`; do for file in `find $rootdir/* -name PKGBUILD`; do + pkgmd5sum=`get_md5checksum $file $pkgdir` + if [ -z $pkgmd5sum ]; then + echo "gensync: error generating checksum for $file" >&2 + rm -rf /tmp/.gensync + exit 1 + fi db_write_entry $file if [ $? -gt 0 ]; then echo "gensync: error writing entry for $file" >&2 diff --git a/scripts/makepkg b/scripts/makepkg index 7cc8b992..10c1c2a0 100755 --- a/scripts/makepkg +++ b/scripts/makepkg @@ -20,7 +20,7 @@ # USA. # -myver='2.6.4' +myver='2.7' startdir=`pwd` # source Arch's abs.conf if it's present @@ -46,7 +46,7 @@ strip_url() { } checkdeps() { - local missdep=`pacman -T $*` + local missdep="" local deplist="" missdep=`pacman -T $*` @@ -77,6 +77,72 @@ checkdeps() { echo $deplist } +handledeps() { + local missingdeps=0 + local deplist="$*" + local haveperm=0 + if [ "`id -u`" = "0" -a "$INFAKEROOT" != "1" ]; then + haveperm=1 + fi + + if [ "$deplist" != "" -a $haveperm -eq 1 ]; then + if [ "$DEP_BIN" = "1" ]; then + # install missing deps from binary packages (using pacman -S) + msg "==> Installing missing dependencies..." + pacman -D $deplist + if [ "$?" = "127" ]; then + msg "==> ERROR: Failed to install missing dependencies." + exit 1 + fi + # TODO: check deps again to make sure they were resolved + elif [ "$DEP_SRC" = "1" ]; then + # install missing deps by building them from source. + # we look for each package name in $ABSROOT and build it. + if [ "$ABSROOT" = "" ]; then + msg "==> ERROR: The ABSROOT environment variable is not defined." + exit 1 + fi + # TODO: handle version comparators (eg, glibc>=2.2.5) + msg "==> Building missing dependencies..." + for dep in $deplist; do + candidates=`find $ABSROOT -type d -name "$dep"` + if [ "$candidates" = "" ]; then + msg "==> ERROR: Could not find \"$dep\" under $ABSROOT" + exit 1 + fi + success=0 + for pkgdir in $candidates; do + if [ -f $pkgdir/PKGBUILD ]; then + cd $pkgdir + if [ "$RMDEPS" = "1" ]; then + makepkg -i -c -b -r -w $PKGDEST + else + makepkg -i -c -b -w $PKGDEST + fi + if [ $? -eq 0 ]; then + success=1 + break + fi + fi + done + if [ "$success" = "0" ]; then + msg "==> ERROR: Failed to build \"$dep\"" + exit 1 + fi + done + # TODO: check deps again to make sure they were resolved + else + missingdeps=1 + fi + elif [ "$deplist" != "" -a $haveperm -eq 0 ]; then + if [ "$DEP_SRC" = "1" -o "$DEP_BIN" = "1" ]; then + msg "==> WARNING: Cannot auto-install missing dependencies as a normal user!" + msg "==> Run makepkg as root to resolve dependencies automatically." + fi + missingdeps=1 + fi + return $missingdeps +} usage() { echo "makepkg version $myver" @@ -92,6 +158,7 @@ usage() { echo " -i, --install Install package after successful build" echo " -n, --nostrip Do not strip binaries/libraries" echo " -p Use an alternate build script (instead of PKGBUILD)" + echo " -r, --rmdeps Remove installed dependencies after a successful build" echo " -s, --syncdeps Install missing dependencies with pacman" echo " -w Write package to instead of the working dir" echo @@ -100,6 +167,7 @@ usage() { echo } + # Options CLEANUP=0 CLEANCACHE=0 @@ -110,6 +178,7 @@ DEP_SRC=0 NODEPS=0 FORCE=0 NOSTRIP=0 +RMDEPS=0 PKGDEST=$startdir BUILDSCRIPT="./PKGBUILD" @@ -117,15 +186,16 @@ ARGLIST=$@ while [ "$#" -ne "0" ]; do case $1 in - --clean) CLEANUP=1 ;; + --clean) CLEANUP=1 ;; --cleancache) CLEANCACHE=1 ;; - --syncdeps) DEP_BIN=1 ;; - --builddeps) DEP_SRC=1 ;; - --nodeps) NODEPS=1 ;; - --install) INSTALL=1 ;; - --force) FORCE=1 ;; - --nostrip) NOSTRIP=1 ;; - --genmd5) GENMD5=1 ;; + --syncdeps) DEP_BIN=1 ;; + --builddeps) DEP_SRC=1 ;; + --nodeps) NODEPS=1 ;; + --install) INSTALL=1 ;; + --force) FORCE=1 ;; + --nostrip) NOSTRIP=1 ;; + --genmd5) GENMD5=1 ;; + --rmdeps) RMDEPS=1 ;; --help) usage exit 0 @@ -135,7 +205,7 @@ while [ "$#" -ne "0" ]; do exit 1 ;; -*) - while getopts "cCsbdhifgnp:w:-" opt; do + while getopts "cCsbdhifgnrp:w:-" opt; do case $opt in c) CLEANUP=1 ;; C) CLEANCACHE=1 ;; @@ -148,6 +218,7 @@ while [ "$#" -ne "0" ]; do n) NOSTRIP=1 ;; w) PKGDEST=$OPTARG ;; p) BUILDSCRIPT=$OPTARG ;; + r) RMDEPS=1 ;; h) usage exit 0 @@ -170,6 +241,11 @@ while [ "$#" -ne "0" ]; do shift done +# convert a (possibly) relative path to absolute +cd $PKGDEST +PKGDEST=`pwd` +cd - + if [ "$CLEANCACHE" = "1" ]; then if [ "`id -u`" = "0" -a "$INFAKEROOT" != "1" ]; then msg "==> Cleaning up source files from the cache." @@ -182,7 +258,7 @@ if [ "$CLEANCACHE" = "1" ]; then fi unset pkgname pkgver pkgrel pkgdesc url groups provides md5sums -unset replaces depends conflicts backup source install build +unset replaces depends conflicts backup source install build makedepends umask 0022 if [ ! -f $BUILDSCRIPT ]; then @@ -240,56 +316,19 @@ fi msg "==> Making package: $pkgname (`date`)" -unset deplist +unset deplist makedeplist if [ `type -p pacman` -a "$NODEPS" = "0" ]; then - msg "==> Checking Dependencies..." + msg "==> Checking Runtime Dependencies..." deplist=`checkdeps ${depends[@]}` - if [ "$deplist" != "" ]; then - if [ "$DEP_BIN" = "1" ]; then - # install missing deps from binary packages (using pacman -S) - msg "==> Installing missing dependencies..." - pacman -D $deplist - if [ "$?" = "127" ]; then - msg "==> ERROR: Failed to install missing dependencies." - exit 1 - fi - # TODO: check deps again to make sure they were resolved - elif [ "$DEP_SRC" = "1" ]; then - # install missing deps by building them from source. - # we look for each package name in $ABSROOT and build it. - if [ "$ABSROOT" = "" ]; then - msg "==> ERROR: The ABSROOT environment variable is not defined." - exit 1 - fi - # TODO: handle version comparators (eg, glibc>=2.2.5) - msg "==> Building missing dependencies..." - for dep in $deplist; do - candidates=`find $ABSROOT -type d -name "$dep"` - if [ "$candidates" = "" ]; then - msg "==> ERROR: Could not find \"$dep\" under $ABSROOT" - exit 1 - fi - success=0 - for pkgdir in $candidates; do - if [ -f $pkgdir/PKGBUILD ]; then - cd $pkgdir - echo makepkg -i -c -b -w $PKGDEST - makepkg -i -c -b -w $PKGDEST - if [ $? -eq 0 ]; then - success=1 - break - fi - fi - done - if [ "$success" = "0" ]; then - msg "==> ERROR: Failed to build \"$dep\"" - exit 1 - fi - done - # TODO: check deps again to make sure they were resolved - else - exit 1 - fi + handledeps $deplist + if [ $? -gt 0 ]; then + exit 1 + fi + msg "==> Checking Buildtime Dependencies..." + makedeplist=`checkdeps ${makedepends[@]}` + handledeps $makedeplist + if [ $? -gt 0 ]; then + exit 1 fi elif [ "$NODEPS" = "1" ]; then msg "==> WARNING: skipping dependency checks." @@ -387,7 +426,7 @@ if [ "$GENMD5" = "0" ]; then *.tar) cmd="tar -xf $file" ;; *.zip) - cmd="unzip -qq $file" ;; + cmd="unzip -qqo $file" ;; *.gz) cmd="gunzip $file" ;; *.bz2) @@ -502,7 +541,7 @@ if [ "$NOSTRIP" = "0" ]; then fi # get some package meta info -builddate=`LC_ALL= ; date -u "+%a %b %e %k:%M:%S %Y"` +builddate=`LC_ALL= ; LANG= ; date -u "+%a %b %e %H:%M:%S %Y"` if [ "$PACKAGER" != "" ]; then packager="$PACKAGER" else @@ -566,14 +605,19 @@ $cmd | sort >../filelist cd $startdir if [ "$CLEANUP" = "1" ]; then - msg "==> Cleaning up" + msg "==> Cleaning up..." rm -rf src pkg filelist fi +if [ "$RMDEPS" = "1" -a "`id -u`" = "0" -a "$INFAKEROOT" != "1" ]; then + msg "==> Removing installed dependencies..." + pacman -R $makedeplist $deplist +fi + msg "==> Finished making: $pkgname (`date`)" -if [ "$INSTALL" = "1" ]; then - msg "==> Running pacman --upgrade" +if [ "$INSTALL" = "1" -a "`id -u`" = "0" -a "$INFAKEROOT" != "1" ]; then + msg "==> Running pacman --upgrade..." pacman --upgrade $PKGDEST/${pkgname}-${pkgver}-${pkgrel}.pkg.tar.gz exit $? fi diff --git a/scripts/makeworld b/scripts/makeworld index 4ce1a772..a5d4c6e8 100755 --- a/scripts/makeworld +++ b/scripts/makeworld @@ -21,7 +21,7 @@ # toplevel=`pwd` -version="2.6.4" +version="2.7" usage() { echo "makeworld version $version" @@ -33,6 +33,7 @@ usage() { echo " -f, --force Overwrite existing packages" echo " -i, --install Install package after successful build" echo " -h, --help This help" + echo " -r, --rmdeps Remove installed dependencies after a successful build" echo " -s, --syncdeps Install missing dependencies with pacman" echo echo " where is one or more directory names under the ABS root" @@ -55,6 +56,7 @@ for arg in $*; do --builddeps) MAKEPKG_OPTS="$MAKEPKG_OPTS -b" ;; --nodeps) MAKEPKG_OPTS="$MAKEPKG_OPTS -d" ;; --force) MAKEPKG_OPTS="$MAKEPKG_OPTS -f" ;; + --rmdeps) MAKEPKG_OPTS="$MAKEPKG_OPTS -r" ;; --help) usage exit 0 @@ -64,7 +66,7 @@ for arg in $*; do exit 1 ;; -*) - while getopts "chisbdf-" opt; do + while getopts "chisbdfr-" opt; do case $opt in c) MAKEPKG_OPTS="$MAKEPKG_OPTS -c" ;; i) MAKEPKG_OPTS="$MAKEPKG_OPTS -i" ;; @@ -72,6 +74,7 @@ for arg in $*; do b) MAKEPKG_OPTS="$MAKEPKG_OPTS -b" ;; d) MAKEPKG_OPTS="$MAKEPKG_OPTS -d" ;; f) MAKEPKG_OPTS="$MAKEPKG_OPTS -f" ;; + r) MAKEPKG_OPTS="$MAKEPKG_OPTS -r" ;; h) usage exit 0 @@ -100,6 +103,11 @@ if [ "$dest" = "" ]; then exit 1 fi +# convert a (possibly) relative path to absolute +cd $dest +dest=`pwd` +cd - + sd=`date +"[%b %d %H:%M]"` for category in $*; do diff --git a/src/db.c b/src/db.c index a9e4270e..862d8020 100644 --- a/src/db.c +++ b/src/db.c @@ -62,21 +62,14 @@ void db_close(pacdb_t* db) /* frees pkgcache if necessary and returns a new package * cache from db */ -PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache) +PMList* db_loadpkgs(pacdb_t *db) { pkginfo_t *info; - PMList *lp; pkginfo_t **arr = NULL; unsigned int arrct = 0; int i; PMList *cache = NULL; - /* if pm_packages already contains data, free it first */ - for(lp = pkgcache; lp; lp = lp->next) { - FREEPKG(lp->data); - } - list_free(pkgcache); - rewinddir(db->dir); while((info = db_scan(db, NULL, INFRQ_DESC)) != NULL) { /* add to the collective */ @@ -168,7 +161,6 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) if(ent == NULL) { return(NULL); } - info = newpkg(); /* we always load DESC */ inforeq |= INFRQ_DESC; @@ -179,12 +171,15 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) return(NULL); } + info = newpkg(); + /* DESC */ if(inforeq & INFRQ_DESC) { snprintf(path, PATH_MAX, "%s/%s/desc", db->path, ent->d_name); fp = fopen(path, "r"); if(fp == NULL) { fprintf(stderr, "error: %s: %s\n", path, strerror(errno)); + FREEPKG(info); return(NULL); } while(!feof(fp)) { @@ -194,16 +189,19 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) trim(line); if(!strcmp(line, "%NAME%")) { if(fgets(info->name, sizeof(info->name), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(info->name); } else if(!strcmp(line, "%VERSION%")) { if(fgets(info->version, sizeof(info->version), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(info->version); } else if(!strcmp(line, "%DESC%")) { if(fgets(info->desc, sizeof(info->desc), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(info->desc); @@ -214,27 +212,32 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) } } else if(!strcmp(line, "%URL%")) { if(fgets(info->url, sizeof(info->url), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(info->url); } else if(!strcmp(line, "%BUILDDATE%")) { if(fgets(info->builddate, sizeof(info->builddate), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(info->builddate); } else if(!strcmp(line, "%INSTALLDATE%")) { if(fgets(info->installdate, sizeof(info->installdate), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(info->installdate); } else if(!strcmp(line, "%PACKAGER%")) { if(fgets(info->packager, sizeof(info->packager), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(info->packager); } else if(!strcmp(line, "%SIZE%")) { char tmp[32]; if(fgets(tmp, sizeof(tmp), fp) == NULL) { + FREEPKG(info); return(NULL); } trim(tmp); @@ -247,6 +250,14 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) char *s = strdup(line); info->replaces = list_add(info->replaces, s); } + } else if(!strcmp(line, "%MD5SUM%")) { + /* MD5SUM tag only appears in sync repositories, + * not the local one. + */ + if(fgets(info->md5sum, sizeof(info->md5sum), fp) == NULL) { + FREEPKG(info); + return(NULL); + } } } fclose(fp); @@ -258,6 +269,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) fp = fopen(path, "r"); if(fp == NULL) { fprintf(stderr, "error: %s: %s\n", path, strerror(errno)); + FREEPKG(info); return(NULL); } while(fgets(line, 256, fp)) { @@ -284,6 +296,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) fp = fopen(path, "r"); if(fp == NULL) { fprintf(stderr, "db_read: error: %s: %s\n", path, strerror(errno)); + FREEPKG(info); return(NULL); } while(!feof(fp)) { diff --git a/src/db.h b/src/db.h index 8f1424ba..a26ad1c2 100644 --- a/src/db.h +++ b/src/db.h @@ -37,7 +37,7 @@ typedef struct __pacdb_t { pacdb_t* db_open(char *root, char *dbpath, char *treename); void db_close(pacdb_t *db); -PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache); +PMList* db_loadpkgs(pacdb_t *db); pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq); pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq); int db_write(pacdb_t *db, pkginfo_t *info); diff --git a/src/list.c b/src/list.c index d3ccfc89..8d1d2820 100644 --- a/src/list.c +++ b/src/list.c @@ -183,6 +183,7 @@ PMList *list_sort(PMList *list) if(arr) { free(arr); + arr = NULL; } return(lp); diff --git a/src/package.c b/src/package.c index cffc2f51..0f6b0c91 100644 --- a/src/package.c +++ b/src/package.c @@ -69,10 +69,12 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output) parse_descfile(descfile, info, &backup, output); if(!strlen(info->name)) { fprintf(stderr, "load_pkg: missing package name in %s.\n", pkgfile); + FREEPKG(info); return(NULL); } if(!strlen(info->version)) { fprintf(stderr, "load_pkg: missing package version in %s.\n", pkgfile); + FREEPKG(info); return(NULL); } for(lp = backup; lp; lp = lp->next) { @@ -123,6 +125,7 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output) char errorstr[255]; snprintf(errorstr, 255, "bad package file in %s", pkgfile); perror(errorstr); + FREEPKG(info); return(NULL); } expath = NULL; @@ -131,6 +134,7 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output) if(!config) { fprintf(stderr, "load_pkg: missing package info file in %s\n", pkgfile); + FREEPKG(info); return(NULL); } @@ -231,6 +235,7 @@ pkginfo_t* newpkg() pkg->builddate[0] = '\0'; pkg->installdate[0] = '\0'; pkg->packager[0] = '\0'; + pkg->md5sum[0] = '\0'; pkg->size = 0; pkg->scriptlet = 0; pkg->requiredby = NULL; diff --git a/src/package.h b/src/package.h index 11547057..b7d72f8f 100644 --- a/src/package.h +++ b/src/package.h @@ -25,6 +25,14 @@ #define FREEPKG(p) { freepkg(p); p = NULL; } +#define FREELISTPKGS(p) {\ + PMList *i;\ + for(i = p; i; i = i->next) {\ + FREEPKG(i->data);\ + }\ + FREELIST(p);\ +} + /* mods for depend_t.mod */ #define DEP_ANY 0 #define DEP_EQ 1 @@ -41,6 +49,7 @@ typedef struct __pkginfo_t { char builddate[32]; char installdate[32]; char packager[64]; + char md5sum[33]; unsigned long size; unsigned short scriptlet; PMList *replaces; diff --git a/src/pacman.c b/src/pacman.c index 03051f92..3c33ac7b 100644 --- a/src/pacman.c +++ b/src/pacman.c @@ -77,6 +77,7 @@ unsigned short pmo_s_clean = 0; unsigned short pmo_group = 0; /* configuration file options */ char *pmo_dbpath = NULL; +char *pmo_logfile = NULL; PMList *pmo_noupgrade = NULL; PMList *pmo_ignorepkg = NULL; unsigned short pmo_usesyslog = 0; @@ -90,6 +91,7 @@ PMList *pm_packages = NULL; /* list of targets specified on command line */ PMList *pm_targets = NULL; +FILE *logfd = NULL; char *lckfile = "/tmp/pacman.lck"; char *workfile = NULL; enum {READ_ONLY, READ_WRITE} pm_access; @@ -108,6 +110,11 @@ int main(int argc, char *argv[]) maxcols = atoi(cenv); } + if(argc < 2) { + usage(PM_MAIN, (char*)basename(argv[0])); + return(0); + } + /* default root */ MALLOC(pmo_root, PATH_MAX); strcpy(pmo_root, "/"); @@ -115,14 +122,11 @@ int main(int argc, char *argv[]) MALLOC(pmo_dbpath, PATH_MAX); strcpy(pmo_dbpath, PKGDIR); - if(argc < 2) { - usage(PM_MAIN, (char*)basename(argv[0])); - return(0); - } - /* parse the command line */ ret = parseargs(PM_ADD, argc, argv); if(ret) { + FREE(pmo_root); + FREE(pmo_dbpath); return(ret); } @@ -160,6 +164,13 @@ int main(int argc, char *argv[]) if(pmo_usesyslog) { openlog("pacman", 0, LOG_USER); } + if(pmo_logfile && geteuid() == 0) { + /* open the log file */ + logfd = fopen(pmo_logfile, "a"); + if(logfd == NULL) { + perror("warning: cannot open logfile"); + } + } /* check for db existence */ /* add a trailing '/' if there isn't one */ @@ -198,7 +209,7 @@ int main(int argc, char *argv[]) } /* load pm_packages cache */ - pm_packages = db_loadpkgs(db_local, pm_packages); + pm_packages = db_loadpkgs(db_local); /* start the requested operation */ switch(pmo_op) { @@ -213,9 +224,6 @@ int main(int argc, char *argv[]) ret = 1; } db_close(db_local); - FREELIST(pm_packages); - FREE(pmo_root); - FREE(pmo_dbpath); cleanup(ret); /* not reached */ return(0); @@ -316,7 +324,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) } oldmask = umask(0000); - if(makepath("/var/cache/pacman/pkg")) { + if(makepath("/var/cache/pacman/pkg")) { fprintf(stderr, "error: could not create new cache directory: %s\n", strerror(errno)); return(1); } @@ -329,9 +337,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) if(pmo_s_sync) { /* grab a fresh package list */ printf(":: Synchronizing package databases... \n"); - if(pmo_usesyslog) { - syslog(LOG_INFO, "synchronizing package lists"); - } + logaction(NULL, "synchronizing package lists"); sync_synctree(); } @@ -351,8 +357,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) dbs->sync = sync; dbs->db = db_sync; /* cache packages */ - dbs->pkgcache = NULL; - dbs->pkgcache = db_loadpkgs(db_sync, dbs->pkgcache); + dbs->pkgcache = db_loadpkgs(db_sync); databases = list_add(databases, dbs); } @@ -454,9 +459,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) } else if(pmo_s_upgrade) { int newer = 0; int ignore = 0; - if(pmo_usesyslog) { - syslog(LOG_INFO, "starting full system upgrade"); - } + logaction(NULL, "starting full system upgrade"); /* check for "recommended" package replacements */ for(i = databases; i && allgood; i = i->next) { dbsync_t *dbs = (dbsync_t*)i->data; @@ -571,58 +574,81 @@ int pacman_sync(pacdb_t *db, PMList *targets) for(i = targets; i && allgood; i = i->next) { if(i->data) { int cmp, found = 0; + char *treename; + char *targ; + char *targline; pkginfo_t *local; syncpkg_t *sync = NULL; MALLOC(sync, sizeof(syncpkg_t)); sync->replaces = NULL; + targline = strdup((char*)i->data); + targ = index(targline, '/'); + if(targ) { + *targ = '\0'; + targ++; + treename = targline; + } else { + targ = targline; + treename = NULL; + } + for(j = databases; !found && j; j = j->next) { dbsync_t *dbs = (dbsync_t*)j->data; for(k = dbs->pkgcache; !found && k; k = k->next) { pkginfo_t *pkg = (pkginfo_t*)k->data; - if(!strcmp((char*)i->data, pkg->name)) { - found = 1; - sync->dbs = dbs; - /* re-fetch the package record with dependency info */ - sync->pkg = db_scan(sync->dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS); - if(sync->pkg == NULL) { - found = 0; + if(!strcmp(targ, pkg->name)) { + if(treename == NULL || + (treename && !strcmp(treename, dbs->sync->treename))) { + found = 1; + sync->dbs = dbs; + /* re-fetch the package record with dependency info */ + sync->pkg = db_scan(sync->dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS); + if(sync->pkg == NULL) { + found = 0; + } } } } } if(!found) { - /* target not found: check if it's a group */ - k = NULL; - for(j = databases; j; j = j->next) { - dbsync_t *dbs = (dbsync_t*)j->data; - PMList *l = pkg_ingroup(dbs->db, (char *)i->data); - k = list_merge(k, l); - FREELIST(l); - } - if(k != NULL) { - printf(":: group %s:\n", (char*)i->data); - list_display(" ", k); - if(yesno(" Install whole content? [Y/n] ")) { - targets = list_merge(targets, k); - FREELIST(k); - } else { - PMList *l; - for(l = k; l; l = l->next) { - if(yesno(":: install %s from group %s? [Y/n] ", (char*)l->data, (char*)i->data)) { - targets = list_add(targets, strdup((char*)l->data)); + if(treename == NULL) { + /* target not found: check if it's a group */ + k = NULL; + for(j = databases; j; j = j->next) { + dbsync_t *dbs = (dbsync_t*)j->data; + PMList *l = pkg_ingroup(dbs->db, targ); + k = list_merge(k, l); + FREELIST(l); + } + if(k != NULL) { + printf(":: group %s:\n", targ); + list_display(" ", k); + if(yesno(" Install whole content? [Y/n] ")) { + targets = list_merge(targets, k); + FREELIST(k); + } else { + PMList *l; + for(l = k; l; l = l->next) { + if(yesno(":: install %s from group %s? [Y/n] ", (char*)l->data, targ)) { + targets = list_add(targets, strdup((char*)l->data)); + } } } + FREELIST(k); + } else { + fprintf(stderr, "%s: not found in sync db\n", targ); + allgood = 0; } - FREELIST(k); } else { - fprintf(stderr, "%s: not found in sync db\n", (char*)i->data); + fprintf(stderr, "%s: not present in \"%s\" repository\n", targ, treename); allgood = 0; } FREE(sync); + FREE(targline); continue; } - local = db_scan(db, (char*)i->data, INFRQ_DESC); + local = db_scan(db, targ, INFRQ_DESC); if(local && !pmo_s_downloadonly) { /* this is an upgrade, compare versions and determine if it is necessary */ cmp = rpmvercmp(local->version, sync->pkg->version); @@ -632,6 +658,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) FREEPKG(local); FREEPKG(sync->pkg); FREE(sync); + FREE(targline); continue; } } else if(cmp == 0) { @@ -640,6 +667,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) FREEPKG(local); FREEPKG(sync->pkg); FREE(sync); + FREE(targline); continue; } } @@ -659,7 +687,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) } } - if(allgood) { + if(allgood && !pmo_s_search) { /* check for inter-conflicts and whatnot */ if(!pmo_nodeps && !pmo_s_downloadonly) { int errorout = 0; @@ -757,7 +785,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) /* any packages in rmtargs need to be removed from final. */ /* rather than ripping out nodes from final, we just copy over */ - /* our "good" nodes to a new list and reassign. */ + /* our "good" nodes to a new list and reassign. */ k = NULL; for(i = final; i; i = i->next) { syncpkg_t *s = (syncpkg_t*)i->data; @@ -779,6 +807,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) /* list targets */ if(final && final->data && allgood) { PMList *list = NULL; + char *str; for(i = rmtargs; i; i = i->next) { list = list_add(list, strdup(i->data)); } @@ -791,9 +820,11 @@ int pacman_sync(pacdb_t *db, PMList *targets) } if(list) { printf("\nRemove: "); - indentprint(buildstring(list), 9); + str = buildstring(list); + indentprint(str, 9); printf("\n"); FREELIST(list); + FREE(str); } for(i = final; i; i = i->next) { syncpkg_t *s = (syncpkg_t*)i->data; @@ -805,9 +836,11 @@ int pacman_sync(pacdb_t *db, PMList *targets) } } printf("\nTargets: "); - indentprint(buildstring(list), 9); + str = buildstring(list); + indentprint(str, 9); printf("\n"); FREELIST(list); + FREE(str); } /* get confirmation */ @@ -835,6 +868,8 @@ int pacman_sync(pacdb_t *db, PMList *targets) PMList *processed = NULL; PMList *files = NULL; + snprintf(ldir, PATH_MAX, "%svar/cache/pacman/pkg", pmo_root); + /* group sync records by repository and download */ while(!done) { if(current) { @@ -853,8 +888,8 @@ int pacman_sync(pacdb_t *db, PMList *targets) struct stat buf; char path[PATH_MAX]; - snprintf(path, PATH_MAX, "%svar/cache/pacman/pkg/%s-%s.pkg.tar.gz", - pmo_root, sync->pkg->name, sync->pkg->version); + snprintf(path, PATH_MAX, "%s/%s-%s.pkg.tar.gz", + ldir, sync->pkg->name, sync->pkg->version); if(stat(path, &buf)) { /* file is not in the cache dir, so add it to the list */ snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); @@ -865,7 +900,6 @@ int pacman_sync(pacdb_t *db, PMList *targets) } } } - snprintf(ldir, PATH_MAX, "%svar/cache/pacman/pkg", pmo_root); if(files) { struct stat buf; @@ -878,14 +912,14 @@ int pacman_sync(pacdb_t *db, PMList *targets) /* no cache directory.... try creating it */ snprintf(parent, PATH_MAX, "%svar/cache/pacman", pmo_root); - logaction("warning: no %s cache exists. creating...\n", ldir); + logaction(stderr, "warning: no %s cache exists. creating...\n", ldir); oldmask = umask(0000); mkdir(parent, 0755); if(mkdir(ldir, 0755)) { /* couldn't mkdir the cache directory, so fall back to /tmp and unlink * the package afterwards. */ - logaction("warning: couldn't create package cache, using /tmp instead\n"); + logaction(stderr, "warning: couldn't create package cache, using /tmp instead\n"); snprintf(ldir, PATH_MAX, "/tmp"); varcache = 0; } @@ -907,6 +941,55 @@ int pacman_sync(pacdb_t *db, PMList *targets) /* double-check */ FREELIST(files); + /* Check integrity of files */ + printf("checking package integrity... "); + fflush(stdout); + + for(i = final; i; i = i->next) { + syncpkg_t *sync; + char str[PATH_MAX], pkgname[PATH_MAX]; + char *md5sum1, *md5sum2; + + sync = (syncpkg_t*)i->data; + snprintf(pkgname, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); + + md5sum1 = sync->pkg->md5sum; + if(md5sum1 == NULL || md5sum1[0] == '\0') { + if(allgood) { + printf("\n"); + } + fprintf(stderr, "error: can't get md5 checksum for package %s\n", pkgname); + allgood = 0; + continue; + } + snprintf(str, PATH_MAX, "%s/%s", ldir, pkgname); + md5sum2 = MDFile(str); + if(md5sum2 == NULL || md5sum2[0] == '\0') { + if(allgood) { + printf("\n"); + } + fprintf(stderr, "error: can't get md5 checksum for archive %s\n", pkgname); + FREE(md5sum1); + allgood = 0; + continue; + } + + if(strcmp(md5sum1, md5sum2) != 0) { + if(allgood) { + printf("\n"); + } + fprintf(stderr, "error: archive %s is corrupted\n", pkgname); + allgood = 0; + } + + FREE(md5sum2); + } + if(allgood) { + printf("done.\n"); + } else { + fprintf(stderr, "\n"); + } + if(!pmo_s_downloadonly) { /* remove any conflicting packages (WITH dep checks) */ if(rmtargs) { @@ -918,7 +1001,8 @@ int pacman_sync(pacdb_t *db, PMList *targets) allgood = 0; } /* reload package cache */ - pm_packages = db_loadpkgs(db, pm_packages); + FREELISTPKGS(pm_packages); + pm_packages = db_loadpkgs(db); } FREELIST(rmtargs); for(i = final; allgood && i; i = i->next) { @@ -996,10 +1080,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) syncpkg_t *sync = (syncpkg_t*)i->data; if(sync) { FREEPKG(sync->pkg); - for(j = sync->replaces; j; j = j->next) { - FREEPKG(j->data); - } - FREELIST(sync->replaces); + FREELISTPKGS(sync->replaces); } FREE(sync); i->data = NULL; @@ -1011,13 +1092,8 @@ int pacman_sync(pacdb_t *db, PMList *targets) for(i = databases; i; i = i->next) { dbsync_t *dbs = (dbsync_t*)i->data; db_close(dbs->db); - for(j = dbs->pkgcache; j; j = j->next) { - if(j->data) { - freepkg(j->data); - j->data = NULL; - } - } - FREELIST(dbs->pkgcache); + dbs->db = NULL; + FREELISTPKGS(dbs->pkgcache); FREE(dbs); i->data = NULL; } @@ -1131,10 +1207,10 @@ int pacman_add(pacdb_t *db, PMList *targets) } if(rmtargs && !errorout) { int retcode; - int oldupg = pmo_upgrade; + int oldupg = pmo_upgrade; /* any packages in rmtargs need to be removed from alltargs. */ /* rather than ripping out nodes from alltargs, we just copy over */ - /* our "good" nodes to a new list and reassign. */ + /* our "good" nodes to a new list and reassign. */ k = NULL; for(lp = alltargs; lp; lp = lp->next) { pkginfo_t *p = (pkginfo_t*)lp->data; @@ -1162,7 +1238,8 @@ int pacman_add(pacdb_t *db, PMList *targets) return(1); } /* reload package cache */ - pm_packages = db_loadpkgs(db, pm_packages); + FREELISTPKGS(pm_packages); + pm_packages = db_loadpkgs(db); pmo_upgrade = oldupg; } } @@ -1236,7 +1313,8 @@ int pacman_add(pacdb_t *db, PMList *targets) return(1); } /* reload package cache */ - pm_packages = db_loadpkgs(db, pm_packages); + FREELISTPKGS(pm_packages); + pm_packages = db_loadpkgs(db); } } else { /* no previous package version is installed, so this is actually just an @@ -1302,8 +1380,8 @@ int pacman_add(pacdb_t *db, PMList *targets) /* extract the package's version to a temporary file and md5 it */ temp = strdup("/tmp/pacman_XXXXXX"); mkstemp(temp); - if(tar_extract_file(tar, temp)) { - logaction("could not extract %s: %s\n", pathname, strerror(errno)); + if(tar_extract_file(tar, temp)) { + logaction(stderr, "could not extract %s: %s\n", pathname, strerror(errno)); errors++; continue; } @@ -1340,13 +1418,13 @@ int pacman_add(pacdb_t *db, PMList *targets) char newpath[PATH_MAX]; snprintf(newpath, PATH_MAX, "%s.pacorig", expath); if(rename(expath, newpath)) { - logaction("error: could not rename %s: %s\n", expath, strerror(errno)); + logaction(stderr, "error: could not rename %s: %s\n", expath, strerror(errno)); } if(copyfile(temp, expath)) { - logaction("error: could not copy %s to %s: %s\n", temp, expath, strerror(errno)); + logaction(stderr, "error: could not copy %s to %s: %s\n", temp, expath, strerror(errno)); errors++; } else { - logaction("warning: %s saved as %s\n", expath, newpath); + logaction(stderr, "warning: %s saved as %s\n", expath, newpath); } } } else if(md5_orig) { @@ -1373,9 +1451,9 @@ int pacman_add(pacdb_t *db, PMList *targets) installnew = 1; snprintf(newpath, PATH_MAX, "%s.pacsave", expath); if(rename(expath, newpath)) { - logaction("error: could not rename %s: %s\n", expath, strerror(errno)); + logaction(stderr, "error: could not rename %s: %s\n", expath, strerror(errno)); } else { - logaction("warning: %s saved as %s\n", expath, newpath); + logaction(stderr, "warning: %s saved as %s\n", expath, newpath); } } @@ -1399,11 +1477,11 @@ int pacman_add(pacdb_t *db, PMList *targets) } else { vprint("%s is in NoUpgrade - skipping\n", pathname); strncat(expath, ".pacnew", PATH_MAX); - logaction("warning: extracting %s%s as %s\n", pmo_root, pathname, expath); + logaction(stderr, "warning: extracting %s%s as %s\n", pmo_root, pathname, expath); /*tar_skip_regfile(tar);*/ } - if(tar_extract_file(tar, expath)) { - logaction("could not extract %s: %s\n", pathname, strerror(errno)); + if(tar_extract_file(tar, expath)) { + logaction(stderr, "could not extract %s: %s\n", pathname, strerror(errno)); errors++; } /* calculate an md5 hash if this is in info->backup */ @@ -1427,7 +1505,7 @@ int pacman_add(pacdb_t *db, PMList *targets) tar_close(tar); if(errors) { ret = 1; - logaction("errors occurred while %s %s\n", + logaction(stderr, "errors occurred while %s %s\n", (pmo_upgrade ? "upgrading" : "installing"), info->name); /* XXX: this "else" is disabled so the db_write() ALWAYS occurs. If it doesn't @@ -1462,17 +1540,15 @@ int pacman_add(pacdb_t *db, PMList *targets) /* make an install date (in UTC) */ strncpy(info->installdate, asctime(gmtime(&t)), sizeof(info->installdate)); if(db_write(db, info)) { - logaction("error updating database for %s!\n", info->name); + logaction(stderr, "error updating database for %s!\n", info->name); return(1); } vprint("done.\n"); - if(pmo_usesyslog) { - if(pmo_upgrade && oldpkg) { - syslog(LOG_INFO, "upgraded %s (%s -> %s)\n", info->name, + if(pmo_upgrade && oldpkg) { + logaction(NULL, "upgraded %s (%s -> %s)", info->name, oldpkg->version, info->version); - } else { - syslog(LOG_INFO, "installed %s (%s)\n", info->name, info->version); - } + } else { + logaction(NULL, "installed %s (%s)", info->name, info->version); } /* update dependency packages' REQUIREDBY fields */ @@ -1678,7 +1754,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) newpath = (char*)realloc(newpath, strlen(line)+strlen(".pacsave")+1); sprintf(newpath, "%s.pacsave", line); rename(line, newpath); - logaction("warning: %s saved as %s\n", line, newpath); + logaction(stderr, "warning: %s saved as %s\n", line, newpath); } else { /*vprint(" unlinking %s\n", line);*/ if(unlink(line)) { @@ -1761,9 +1837,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) } if(!pmo_upgrade) { printf("done.\n"); - if(pmo_usesyslog) { - syslog(LOG_INFO, "removed %s (%s)\n", info->name, info->version); - } + logaction(NULL, "removed %s (%s)\n", info->name, info->version); } } @@ -1865,7 +1939,7 @@ int pacman_query(pacdb_t *db, PMList *targets) int gotcha = 0; rewinddir(db->dir); while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_FILES)) != NULL && !gotcha) { - for(lp = info->files; lp; lp = lp->next) { + for(lp = info->files; lp && !gotcha; lp = lp->next) { sprintf(path, "%s%s", pmo_root, (char*)lp->data); if(!strcmp(path, rpath)) { printf("%s is owned by %s %s\n", package, info->name, info->version); @@ -1915,12 +1989,45 @@ int pacman_query(pacdb_t *db, PMList *targets) } else { /* find a target */ if(pmo_q_info) { - info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS); + info = db_scan(db, package, INFRQ_ALL); if(info == NULL) { fprintf(stderr, "Package \"%s\" was not found.\n", package); return(2); } dump_pkg(info); + if(pmo_q_info > 1 && info->backup) { + /* extra info */ + printf("\n"); + for(lp = info->backup; lp; lp = lp->next) { + struct stat buf; + char path[PATH_MAX]; + char *md5sum; + char *str = strdup(lp->data); + char *ptr = index(str, '\t'); + if(ptr == NULL) { + FREE(str); + continue; + } + *ptr = '\0'; + ptr++; + snprintf(path, PATH_MAX-1, "%s%s", pmo_root, str); + if(!stat(path, &buf)) { + md5sum = MDFile(path); + if(md5sum == NULL) { + fprintf(stderr, "error calculating md5sum for %s\n", path); + continue; + } + if(strcmp(md5sum, ptr)) { + printf("MODIFIED\t%s\n", path); + } else { + printf("NOT MODIFIED\t%s\n", path); + } + } else { + printf("MISSING\t\t%s\n", path); + } + FREE(str); + } + } printf("\n"); } else if(pmo_q_list) { info = db_scan(db, package, INFRQ_DESC | INFRQ_FILES); @@ -2319,7 +2426,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) for(j = tp->depends; j; j = j->next) { /* split into name/version pairs */ if(splitdep((char*)j->data, &depend)) { - logaction("warning: invalid dependency in %s\n", (char*)tp->name); + logaction(stderr, "warning: invalid dependency in %s\n", (char*)tp->name); continue; } found = 0; @@ -2477,6 +2584,7 @@ int splitdep(char *depstr, depend_t *depend) } if(ptr == NULL) { + FREE(str); return(0); } *ptr = '\0'; @@ -2589,7 +2697,7 @@ int parseargs(int op, int argc, char **argv) case 'e': pmo_q_orphans = 1; break; case 'f': pmo_force = 1; break; case 'g': pmo_group = 1; break; - case 'i': pmo_q_info = 1; break; + case 'i': pmo_q_info++; break; case 'l': pmo_q_list = 1; break; case 'n': pmo_nosave = 1; break; case 'p': pmo_q_isfile = 1; break; @@ -2735,6 +2843,9 @@ int parseconfig(char *configfile) } strncpy(pmo_dbpath, ptr, PATH_MAX); vprint("config: dbpath: %s\n", pmo_dbpath); + } else if (!strcmp(key, "LOGFILE")) { + pmo_logfile = strndup(ptr, PATH_MAX); + vprint("config: log file: %s\n", pmo_logfile); } else { fprintf(stderr, "config: line %d: syntax error\n", linenum); return(1); @@ -2898,19 +3009,29 @@ void vprint(char *fmt, ...) } } -/* Output a message to stderr, and (optionally) syslog */ -void logaction(char *fmt, ...) +/* Output a message to stderr, and (optionally) syslog and/or a logfile */ +void logaction(FILE *fp, char *fmt, ...) { char msg[1024]; va_list args; va_start(args, fmt); vsnprintf(msg, 1024, fmt, args); va_end(args); - - fprintf(stderr, "%s", msg); + if(fp) { + fprintf(fp, "%s", msg); + } if(pmo_usesyslog) { syslog(LOG_WARNING, "%s", msg); } + if(logfd) { + time_t t; + struct tm *tm; + t = time(NULL); + tm = localtime(&t); + + fprintf(logfd, "[%02d/%02d/%02d %02d:%02d] %s\n", tm->tm_mon, tm->tm_mday, + tm->tm_year-100, tm->tm_hour, tm->tm_min, msg); + } } /* Condense a list of strings into one long (space-delimited) string @@ -2958,8 +3079,10 @@ int lckrm(char *file) void cleanup(int signum) { + PMList *lp; + if(pm_access == READ_WRITE && lckrm(lckfile)) { - logaction("warning: could not remove lock file %s\n", lckfile); + logaction(stderr, "warning: could not remove lock file %s\n", lckfile); } if(workfile) { /* remove the current file being downloaded (as it's not complete) */ @@ -2969,6 +3092,34 @@ void cleanup(int signum) if(pmo_usesyslog) { closelog(); } + if(logfd) { + fclose(logfd); + } + + /* free memory */ + for(lp = pmc_syncs; lp; lp = lp->next) { + sync_t *sync = (sync_t *)lp->data; + PMList *i; + for(i = sync->servers; i; i = i->next) { + server_t *server = (server_t *)i->data; + FREE(server->protocol); + FREE(server->server); + FREE(server->path); + } + FREELIST(sync->servers); + FREE(sync->treename); + } + FREELIST(pmc_syncs); + FREELIST(pmo_noupgrade); + FREELIST(pmo_ignorepkg); + FREE(pmo_root); + FREE(pmo_dbpath); + + FREELIST(pm_targets); + + /* this is segfaulting... quick fix for now + FREELISTPKGS(pm_packages);*/ + exit(signum); } diff --git a/src/pacman.h b/src/pacman.h index f5d8ca3d..5828f8cc 100644 --- a/src/pacman.h +++ b/src/pacman.h @@ -22,7 +22,7 @@ #define _PAC_PACMAN_H #ifndef PACVER -#define PACVER "2.6.4" +#define PACVER "2.7" #endif #ifndef PKGDIR @@ -64,7 +64,7 @@ void usage(int op, char *myname); void version(void); void vprint(char *fmt, ...); -void logaction(char *fmt, ...); +void logaction(FILE *fp, char *fmt, ...); char* buildstring(PMList *strlist); int lckmk(char *file, int retries, unsigned int sleep_secs); int lckrm(char *lckfile); -- cgit v1.2.3-24-g4f1b