diff options
128 files changed, 2966 insertions, 3045 deletions
| diff --git a/config.guess b/config.guess index 951383e3..f2a0acfb 100755 --- a/config.guess +++ b/config.guess @@ -1,10 +1,10 @@  #! /bin/sh  # Attempt to guess a canonical system name.  #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -#   Inc. +#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +#   Free Software Foundation, Inc. -timestamp='2007-05-17' +timestamp='2008-01-23'  # This file is free software; you can redistribute it and/or modify it  # under the terms of the GNU General Public License as published by @@ -56,8 +56,8 @@ version="\  GNU config.guess ($timestamp)  Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.  This is free software; see the source for copying conditions.  There is NO  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -330,7 +330,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in      sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)  	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`  	exit ;; -    i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*) +    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)  	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`  	exit ;;      sun4*:SunOS:6*:*) @@ -532,7 +532,7 @@ EOF  		echo rs6000-ibm-aix3.2  	fi  	exit ;; -    *:AIX:*:[45]) +    *:AIX:*:[456])  	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`  	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then  		IBM_ARCH=rs6000 @@ -793,12 +793,15 @@ EOF  	exit ;;      *:Interix*:[3456]*)      	case ${UNAME_MACHINE} in -	    x86)  +	    x86)  		echo i586-pc-interix${UNAME_RELEASE}  		exit ;;  	    EM64T | authenticamd)  		echo x86_64-unknown-interix${UNAME_RELEASE}  		exit ;; +	    IA64) +		echo ia64-unknown-interix${UNAME_RELEASE} +		exit ;;  	esac ;;      [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)  	echo i${UNAME_MACHINE}-pc-mks @@ -833,7 +836,14 @@ EOF  	echo ${UNAME_MACHINE}-pc-minix  	exit ;;      arm*:Linux:*:*) -	echo ${UNAME_MACHINE}-unknown-linux-gnu +	eval $set_cc_for_build +	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ +	    | grep -q __ARM_EABI__ +	then +	    echo ${UNAME_MACHINE}-unknown-linux-gnu +	else +	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi +	fi  	exit ;;      avr32*:Linux:*:*)  	echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -954,8 +964,8 @@ EOF      x86_64:Linux:*:*)  	echo x86_64-unknown-linux-gnu  	exit ;; -    xtensa:Linux:*:*) -    	echo xtensa-unknown-linux-gnu +    xtensa*:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-gnu  	exit ;;      i*86:Linux:*:*)  	# The BFD linker knows what the default object file format is, so @@ -1474,9 +1484,9 @@ This script, last modified $timestamp, has failed to recognize  the operating system you are using. It is advised that you  download the most up to date version of the config scripts from -  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess +  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD  and -  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub +  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD  If the version you run ($0) is already up to date, please  send the following data and any information you think might be @@ -1,10 +1,10 @@  #! /bin/sh  # Configuration validation subroutine script.  #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -#   Inc. +#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +#   Free Software Foundation, Inc. -timestamp='2007-04-29' +timestamp='2008-01-16'  # This file is (in principle) common to ALL GNU software.  # The presence of a machine in this file suggests that SOME GNU software @@ -72,8 +72,8 @@ Report bugs and patches to <config-patches@gnu.org>."  version="\  GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.  This is free software; see the source for copying conditions.  There is NO  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -369,10 +369,14 @@ case $basic_machine in  	| v850-* | v850e-* | vax-* \  	| we32k-* \  	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ -	| xstormy16-* | xtensa-* \ +	| xstormy16-* | xtensa*-* \  	| ymp-* \  	| z8k-*)  		;; +	# Recognize the basic CPU types without company name, with glob match. +	xtensa*) +		basic_machine=$basic_machine-unknown +		;;  	# Recognize the various machine names and aliases which stand  	# for a CPU type and a company and sometimes even an OS.  	386bsd) @@ -443,6 +447,14 @@ case $basic_machine in  		basic_machine=ns32k-sequent  		os=-dynix  		;; +	blackfin) +		basic_machine=bfin-unknown +		os=-linux +		;; +	blackfin-*) +		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` +		os=-linux +		;;  	c90)  		basic_machine=c90-cray  		os=-unicos @@ -475,8 +487,8 @@ case $basic_machine in  		basic_machine=craynv-cray  		os=-unicosmp  		;; -	cr16c) -		basic_machine=cr16c-unknown +	cr16) +		basic_machine=cr16-unknown  		os=-elf  		;;  	crds | unos) @@ -668,6 +680,14 @@ case $basic_machine in  		basic_machine=m68k-isi  		os=-sysv  		;; +	m68knommu) +		basic_machine=m68k-unknown +		os=-linux +		;; +	m68knommu-*) +		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` +		os=-linux +		;;  	m88k-omron*)  		basic_machine=m88k-omron  		;; @@ -813,6 +833,14 @@ case $basic_machine in  		basic_machine=i860-intel  		os=-osf  		;; +	parisc) +		basic_machine=hppa-unknown +		os=-linux +		;; +	parisc-*) +		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` +		os=-linux +		;;  	pbd)  		basic_machine=sparc-tti  		;; @@ -1021,6 +1049,10 @@ case $basic_machine in  		basic_machine=tic6x-unknown  		os=-coff  		;; +	tile*) +		basic_machine=tile-unknown +		os=-linux-gnu +		;;  	tx39)  		basic_machine=mipstx39-unknown  		;; diff --git a/configure.ac b/configure.ac index eabb4a4e..27efd170 100644 --- a/configure.ac +++ b/configure.ac @@ -51,16 +51,15 @@ m4_define([lib_revision], [1])  m4_define([lib_age], [3])  m4_define([pacman_version_major], [3]) -m4_define([pacman_version_minor], [1]) -m4_define([pacman_version_micro], [4]) -m4_define([pacman_version_suffix], []) +m4_define([pacman_version_minor], [2]) +m4_define([pacman_version_micro], [0]) +m4_define([pacman_version_suffix], [devel])  m4_define([pacman_version],            [pacman_version_major.pacman_version_minor.pacman_version_micro])  m4_define([pacman_display_version],  					pacman_version[]m4_ifdef([pacman_version_suffix],[pacman_version_suffix]))  # Autoconf initialization -# AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)  AC_INIT([Pacman Package Manager], [pacman_display_version],          [pacman-dev@archlinux.org], [pacman])  AC_CONFIG_SRCDIR([config.h.in]) @@ -80,47 +79,52 @@ AC_DEFINE_UNQUOTED([LIB_VERSION], ["$LIB_VERSION"], [libalpm version number])  # Help line for root directory  AC_ARG_WITH(root-dir, -	AC_HELP_STRING([--with-root-dir=path], [set the location of pacman's root operating directory]), +	AS_HELP_STRING([--with-root-dir=path], [set the location of pacman's root operating directory]),  	[ROOTDIR=$withval], [ROOTDIR=/])  # Help line for package extension  AC_ARG_WITH(pkg-ext, -	AC_HELP_STRING([--with-pkg-ext=ext], [set the file extension used by packages]), +	AS_HELP_STRING([--with-pkg-ext=ext], [set the file extension used by packages]),  	[PKGEXT=$withval], [PKGEXT=.pkg.tar.gz])  # Help line for source package directory  AC_ARG_WITH(src-ext, -	AC_HELP_STRING([--with-src-ext=ext], [set the file extension used by source packages]), +	AS_HELP_STRING([--with-src-ext=ext], [set the file extension used by source packages]),  	[SRCEXT=$withval], [SRCEXT=.src.tar.gz])  # Help line for database extension  AC_ARG_WITH(db-ext, -	AC_HELP_STRING([--with-db-ext=ext], [set the file extension used by the database]), +	AS_HELP_STRING([--with-db-ext=ext], [set the file extension used by the database]),  	[DBEXT=$withval], [DBEXT=.db.tar.gz]) +# Help line for libdownload/libfetch +AC_ARG_ENABLE(internal-download, +	AS_HELP_STRING([--disable-internal-download], [do not build with libdownload/libfetch support]), +	[internaldownload=$enableval], [internaldownload=yes]) +  # Help line for documentation  AC_ARG_ENABLE(doc, -	AC_HELP_STRING([--disable-doc], [prevent make from looking at doc/ dir]), +	AS_HELP_STRING([--disable-doc], [prevent make from looking at doc/ dir]),  	[wantdoc=$enableval], [wantdoc=yes])  # Help line for doxygen  AC_ARG_ENABLE(doxygen, -	AC_HELP_STRING([--enable-doxygen], [build your own API docs via Doxygen]), +	AS_HELP_STRING([--enable-doxygen], [build your own API docs via Doxygen]),  	[wantdoxygen=$enableval], [wantdoxygen=no])  # Help line for asciidoc  AC_ARG_ENABLE(asciidoc, -	AC_HELP_STRING([--enable-asciidoc], [build your own manpages with Asciidoc]), +	AS_HELP_STRING([--enable-asciidoc], [build your own manpages with Asciidoc]),  	[wantasciidoc=$enableval], [wantasciidoc=no])  # Help line for debug  AC_ARG_ENABLE(debug, -	AC_HELP_STRING([--enable-debug], [enable debugging support]), +	AS_HELP_STRING([--enable-debug], [enable debugging support]),  	[debug=$enableval], [debug=no])  # Help line for pacman.static  AC_ARG_ENABLE(pacman-static, -	AC_HELP_STRING([--disable-pacman-static], [do not build static version of pacman]), +	AS_HELP_STRING([--disable-pacman-static], [do not build static version of pacman]),  	[pacmanstatic=$enableval], [pacmanstatic=yes])  # Checks for programs. @@ -129,7 +133,6 @@ AC_PROG_CC_C99  AC_PROG_INSTALL  AC_PROG_LN_S  AC_PROG_MAKE_SET -AC_PROG_RANLIB  AC_PROG_LIBTOOL  AC_CHECK_PROGS([PYTHON], [python2.5 python2.4 python], [false]) @@ -138,13 +141,27 @@ AM_GNU_GETTEXT([external])  AM_GNU_GETTEXT_VERSION(0.13.1)  # Check for libarchive -AC_CHECK_LIB([archive], [archive_read_data], , AC_MSG_ERROR([libarchive is needed to compile pacman!])) - -# Check for libdownload -AC_CHECK_LIB([download], [downloadParseURL], , AC_MSG_ERROR([libdownload is needed to compile pacman!])) +AC_CHECK_LIB([archive], [archive_read_data], , +	AC_MSG_ERROR([libarchive is needed to compile pacman!])) + +# Enable or disable usage of libdownload/libfetch +# - this is a nested check- first see if we need a library, if we do then +#   check for libdownload first, then fallback to libfetch, then die +AC_MSG_CHECKING(whether to link with download library) +if test "x$internaldownload" = "xyes" ; then +	AC_MSG_RESULT(yes) +	AC_DEFINE([INTERNAL_DOWNLOAD], , [Use internal download library]) +	# Check for a download library if it was actually requested +	AC_CHECK_LIB([download], [downloadParseURL], , +		AC_CHECK_LIB([fetch], [fetchParseURL], , +			AC_MSG_ERROR([libdownload or libfetch are needed to compile with internal download support])) ) +else +	AC_MSG_RESULT(no) +fi +AM_CONDITIONAL(INTERNAL_DOWNLOAD, test "x$internaldownload" = "xyes")  # Checks for header files. -AC_CHECK_HEADERS([fcntl.h libintl.h limits.h locale.h string.h strings.h sys/ioctl.h sys/statvfs.h sys/time.h syslog.h wchar.h]) +AC_CHECK_HEADERS([fcntl.h libintl.h limits.h locale.h string.h strings.h sys/ioctl.h sys/param.h sys/statvfs.h sys/syslimits.h sys/time.h syslog.h wchar.h])  # Checks for typedefs, structures, and compiler characteristics.  AC_C_INLINE @@ -156,13 +173,13 @@ AC_STRUCT_TM  AC_TYPE_UID_T  # Checks for library functions. -AC_FUNC_CLOSEDIR_VOID  AC_FUNC_FORK  AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK  AC_FUNC_MKTIME  AC_TYPE_SIGNAL -AC_CHECK_FUNCS([geteuid realpath regcomp strcasecmp strdup strerror \ -								strndup strrchr strsep strstr strverscmp swprintf uname]) +AC_CHECK_FUNCS([geteuid realpath regcomp strcasecmp \ +                strndup strrchr strsep strverscmp swprintf \ +                wcwidth uname])  # Enable large file support if available  AC_SYS_LARGEFILE @@ -360,6 +377,7 @@ pacman_display_version:    Compilation options:      Run make in doc/ dir   : ${wantdoc} +    Use download library   : ${internaldownload}      Doxygen support        : ${usedoxygen}      Asciidoc support       : ${useasciidoc}      debug support          : ${debug} diff --git a/contrib/.gitignore b/contrib/.gitignore deleted file mode 100644 index e69de29b..00000000 --- a/contrib/.gitignore +++ /dev/null diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 7066f409..7eee91a1 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -1,9 +1,11 @@  EXTRA_DIST = \  	PKGBUILD.vim \  	bash_completion \ +	gensync \  	pacdiff \  	pacsearch \  	re-pacman \ +	updatesync \  	vimprojects \  	wget-xdelta.sh \  	zsh_completion \ diff --git a/contrib/PKGBUILD.vim b/contrib/PKGBUILD.vim index 57e4cf0e..8f45ae44 100644 --- a/contrib/PKGBUILD.vim +++ b/contrib/PKGBUILD.vim @@ -151,7 +151,7 @@ hi def link pbValidSha1sums  Number  " options  syn keyword pb_k_options options contained -syn match pbOptions /\(no\)\?\(strip\|docs\|libtool\|emptydirs\|ccache\|distcc\|makeflags\|force\)/ contained +syn match pbOptions /\(no\)\?\(strip\|docs\|libtool\|emptydirs\|zipman\|ccache\|distcc\|makeflags\|force\)/ contained  syn match   pbOptionsNeg     /\!/ contained  syn match   pbOptionsDeprec  /no/ contained  syn region pbOptionsGroup start=/^options=(/ end=/)/ contains=pb_k_options,pbOptions,pbOptionsNeg,pbOptionsDeprec,pbIllegalOption,shDoubleQuote,shSingleQuote diff --git a/contrib/README b/contrib/README index 7eb36aae..1a1b6a9c 100644 --- a/contrib/README +++ b/contrib/README @@ -24,3 +24,7 @@ vimprojects - a project file for the vim project plugin.  wget-xdelta.sh - A download script for pacman which allows binary deltas  generated with makepkg to be used instead of downloading full binary packages.  This should cut download sizes for some package upgrades significantly. + +gensync, updatesync - The former repository management scripts that have since +been superseded by repo-add and repo-remove. They are here for posterity's +sake, and to show how repo-add and repo-remove can be wrapped in other scripts. diff --git a/contrib/bash_completion b/contrib/bash_completion index 77192858..11f021c8 100644 --- a/contrib/bash_completion +++ b/contrib/bash_completion @@ -146,14 +146,13 @@ _pacman ()      toparse="${a:2}"      case "${arg}" in -      -@(A|U|R|S|Q|h|V)) +      -@(U|R|S|Q|h|V))          op="${arg/-}"          mod="${mod}${a:2}"          ;;        --)          arg="${a:2}"          case "${arg}" in -          add) op="A" ;;            remove) op="R" ;;            upgrade) op="U" ;;            query) op="Q" ;; @@ -187,6 +186,7 @@ _pacman ()            dbonly) mod="${mod}k" ;;            nosave) mod="${mod}n" ;;            recursive) mod="${mod}s" ;; +          unneeded) mod="${mod}u" ;;          esac ;;        *) toparse="${a}" ;;      esac @@ -202,7 +202,6 @@ _pacman ()    if [ $COMP_CWORD -eq 1 ] && [[ "$cur" == -* ]]; then      COMPREPLY=( $( compgen -W '\ -      -A --add \        -h --help \        -Q --query \        -R --remove \ @@ -216,9 +215,10 @@ _pacman ()    if [[ "$cur" == -* ]]; then      case "${op}" in -      A|U) +      U)          COMPREPLY=( $( compgen -W '\            --asdeps \ +          --asexplicit \            -d --nodeps \            -f --force \            -h --help \ @@ -242,6 +242,7 @@ _pacman ()            -k --dbonly \            -n --nosave \            -s --recursive \ +          -u --unneeded \            --config \            --logfile \            --noconfirm \ @@ -257,9 +258,9 @@ _pacman ()        S)          COMPREPLY=( $( compgen -W '\            --asdeps \ +          --asexplicit \            -c --clean \            -d --nodeps \ -          -e --dependsonly \            -f --force \            -g --groups \            -h --help \ @@ -316,7 +317,7 @@ _pacman ()      rem_selected    else      case "${op}" in -      A|U) +      U)          COMPREPLY=( $( compgen -d -- "$cur" ) \                      $( compgen -f -X '!*.pkg.tar.gz' -- "$cur" ) )          return 0 diff --git a/scripts/gensync.sh.in b/contrib/gensync index d5dec275..51d32ceb 100644..100755 --- a/scripts/gensync.sh.in +++ b/contrib/gensync @@ -1,7 +1,6 @@  #!/bin/bash  #  #   gensync -#   @configure_input@  #  #   Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org>  # @@ -19,42 +18,35 @@  #   along with this program.  If not, see <http://www.gnu.org/licenses/>.  # -# gettext initialization -export TEXTDOMAIN='pacman' -export TEXTDOMAINDIR='@localedir@' - -myver='@PACKAGE_VERSION@' +myver='3.1.1'  # functions  usage() {  	printf "gensync (pacman) %s\n\n" "$myver" -	printf "$(gettext "Usage: %s <root> <destfile> [package_directory]")\n\n" "$0" -	printf "$(gettext "\ -NOTE: this script is DEPRECATED. It will be removed in the next major\n\ -release of pacman, so please use repo-add and repo-remove instead.\n\n")" -	printf "$(gettext "\ +	printf "Usage: %s <root> <destfile> [package_directory]\n\n" "$0" +	printf "\  gensync will generate a sync database by reading all PKGBUILD files\n\  from <root>. gensync builds the database in a temporary directory\n\ -and then compresses it to <destfile>.\n\n")" -	printf "$(gettext "\ +and then compresses it to <destfile>.\n\n" +	printf "\  gensync will calculate md5sums of packages in the same directory as\n\ -<destfile>, unless an alternate [package_directory] is specified.\n\n")" -	printf "$(gettext "\ +<destfile>, unless an alternate [package_directory] is specified.\n\n" +	printf "\  note: The <destfile> name is important. It must be of the form\n\        {treename}.db.tar.gz where {treename} is the name of the custom\n\        package repository you configured in /etc/pacman.conf. The\n\        generated database must reside in the same directory as your\n\ -      custom packages (also configured in /etc/pacman.conf)\n\n")" -	echo "$(gettext "Example:  gensync /var/abs/local /home/mypkgs/custom.db.tar.gz")" +      custom packages (also configured in /etc/pacman.conf)\n\n" +	echo "Example:  gensync /var/abs/local /home/mypkgs/custom.db.tar.gz"  }  version() {  	printf "gensync (pacman) %s\n" "$myver" -	printf "$(gettext "\ +	printf "\  Copyright (C) 2002-2007 Judd Vinet <jvinet@zeroflux.org>.\n\n\  This is free software; see the source for copying conditions.\n\ -There is NO WARRANTY, to the extent permitted by law.\n")" +There is NO WARRANTY, to the extent permitted by law.\n"  }  error () { @@ -67,26 +59,8 @@ die () {  	exit 1  } -check_force () { -	local i -	for i in ${options[@]}; do -		local lc=$(echo $i | tr [:upper:] [:lower:]) -		if [ "$lc" = "force" ]; then -			true -		fi -	done -	false -} -  # PROGRAM START -# determine whether we have gettext; make it a no-op if we do not -if [ ! $(type -t gettext) ]; then -	gettext() { -		echo "$@" -	} -fi -  if [ "$1" = "-h" -o "$1" = "--help" ]; then  	usage  	exit 0 @@ -103,10 +77,10 @@ if [ $# -lt 2 ]; then  fi  # source system and user makepkg.conf -if [ -r @sysconfdir@/makepkg.conf ]; then -	source @sysconfdir@/makepkg.conf +if [ -r /etc/makepkg.conf ]; then +	source /etc/makepkg.conf  else -	die "$(gettext "%s not found. Can not continue.")" "@sysconfdir@/makepkg.conf" +	die "/etc/makepkg.conf not found. Cannot continue."  fi  if [ -r ~/.makepkg.conf ]; then @@ -124,22 +98,17 @@ if [ "$3" != "" ]; then  	pkgdir="$3"  fi -[ ! -d "$rootdir" ] && die "$(gettext "invalid root dir: %s")" $rootdir - -printf "$(gettext "\ -NOTE: this script is DEPRECATED. It will be removed in the next major\n\ -release of pacman, so please use repo-add and repo-remove instead.\n\n")" +[ ! -d "$rootdir" ] && die "invalid root dir: $rootdir" -echo "$(gettext "gensync: building database entries, generating md5sums...")" >&2 +echo "gensync: building database entries, generating md5sums..." >&2  cd "$destdir"  pkgs="" -forcepkgs=""  for file in $(find "$rootdir"/* -name "$BUILDSCRIPT"); do  	unset pkgname pkgver pkgrel options -	source $file || die "$(gettext "failed to parse %s")" $file +	source $file || die "failed to parse $file"  	if [ "$arch" = 'any' ]; then  		CARCH='any'  	fi @@ -150,20 +119,16 @@ for file in $(find "$rootdir"/* -name "$BUILDSCRIPT"); do  	fi  	if [ ! -f "$pkgfile" ]; then -		error "$(gettext "could not find %s-%s-%s-%s%s - skipping")" $pkgname $pkgver $pkgrel $CARCH $PKGEXT +		error "could not find %s-%s-%s-%s%s - skipping" $pkgname $pkgver $pkgrel $CARCH $PKGEXT  	else -		if check_force; then -			forcepkgs="$forcepkgs $pkgfile" -		else -			pkgs="$pkgs $pkgfile" -		fi +		pkgs="$pkgs $pkgfile"  	fi  done -echo "$(gettext "creating repo DB...")" +echo "creating repo DB..."  # we'll trim the output just a tad, as gensync may be used on large repos -repo-add $destfile $pkgs --force $force_pkgs \ +repo-add $destfile $pkgs \  		| grep -e "package" -e "database"  # vim: set ts=2 sw=2 noet: diff --git a/scripts/updatesync.sh.in b/contrib/updatesync index 5f5cc6c9..f88e8237 100644..100755 --- a/scripts/updatesync.sh.in +++ b/contrib/updatesync @@ -1,7 +1,6 @@  #!/bin/bash  #  #   updatesync -#   @configure_input@  #  #   Copyright (c) 2004 by Jason Chu <jason@archlinux.org>  #   Derived from gensync (c) 2002-2006 Judd Vinet <jvinet@zeroflux.org> @@ -20,40 +19,33 @@  #   along with this program.  If not, see <http://www.gnu.org/licenses/>.  # -# gettext initialization -export TEXTDOMAIN='pacman' -export TEXTDOMAINDIR='@localedir@' - -myver='@PACKAGE_VERSION@' +myver='3.1.1'  # functions  usage() {  	printf "updatesync (pacman) %s\n\n" "$myver" -	printf "$(gettext "Usage: %s <action> <destfile> <option> [package_directory]")\n\n" "$0" -	printf "$(gettext "\ -NOTE: this script is DEPRECATED. It will be removed in the next major\n\ -release of pacman, so please use repo-add and repo-remove instead.\n\n")" -	printf "$(gettext "\ +	printf "Usage: %s <action> <destfile> <option> [package_directory]\n\n" "$0" +	printf "\  updatesync will update a sync database by reading a PKGBUILD and\n\  modifying the destfile. updatesync updates the database in a temporary\n\ -directory and then compresses it to <destfile>.\n\n")" -	printf "$(gettext "There are two types of actions:\n\n")" -	printf "$(gettext "upd - Will update a package's entry or create it if it doesn't exist.\n      It takes the package's PKGBUILD as an option.\n")" -	printf "$(gettext "del - Will remove a package's entry from the db. It takes the package's\n      name as an option.\n")" +directory and then compresses it to <destfile>.\n\n" +	printf "There are two types of actions:\n\n" +	printf "upd - Will update a package's entry or create it if it doesn't exist.\n      It takes the package's PKGBUILD as an option.\n" +	printf "del - Will remove a package's entry from the db. It takes the package's\n      name as an option.\n"  	echo -	printf "$(gettext "\ +	printf "\  updatesync will calculate md5sums of packages in the same directory as\n\ -<destfile>, unless an alternate [package_directory] is specified.\n\n")" -	echo "$(gettext "Example:  updatesync upd /home/mypkgs/custom.db.tar.gz PKGBUILD")" +<destfile>, unless an alternate [package_directory] is specified.\n\n" +	echo "Example:  updatesync upd /home/mypkgs/custom.db.tar.gz PKGBUILD"  }  version() {  	printf "updatesync (pacman) %s\n" "$myver" -	printf "$(gettext "\ +	printf "\  Copyright (C) 2004 Jason Chu <jason@archlinux.org>.\n\n\  This is free software; see the source for copying conditions.\n\ -There is NO WARRANTY, to the extent permitted by law.\n")" +There is NO WARRANTY, to the extent permitted by law.\n"  }  error () { @@ -66,26 +58,8 @@ die () {  	exit 1  } -check_force () { -	local i -	for i in ${options[@]}; do -		local lc=$(echo $i | tr [:upper:] [:lower:]) -		if [ "$lc" = "force" ]; then -			true -		fi -	done -	false -} -  # PROGRAM START -# determine whether we have gettext; make it a no-op if we do not -if [ ! $(type -t gettext) ]; then -	gettext() { -		echo "$@" -	} -fi -  if [ "$1" = "-h" -o "$1" = "--help" ]; then  	usage  	exit 0 @@ -102,10 +76,10 @@ if [ $# -lt 3 ]; then  fi  # source system and user makepkg.conf -if [ -r @sysconfdir@/makepkg.conf ]; then -	source @sysconfdir@/makepkg.conf +if [ -r /etc/makepkg.conf ]; then +	source /etc/makepkg.conf  else -	die "$(gettext "%s not found. Can not continue.")" "@sysconfdir@/makepkg.conf" +	die "/etc/makepkg.conf not found. Cannot continue."  fi  if [ -r ~/.makepkg.conf ]; then @@ -124,39 +98,30 @@ pkgdir="$(pwd)"  if [ "$4" != "" ]; then  	pkgdir="$4"  fi -opt_force="" - -printf "$(gettext "\ -NOTE: this script is DEPRECATED. It will be removed in the next major\n\ -release of pacman, so please use repo-add and repo-remove instead.\n\n")"  if [ "$action" = "upd" ]; then # INSERT / UPDATE  	if [ ! -f "$option" ]; then -		die "$(gettext "%s not found")" $option +		die "$option not found"  	fi  	unset pkgname pkgver pkgrel options -	source $option || die "$(gettext "failed to parse %s")" $option +	source $option || die "failed to parse $option"  	if [ "$arch" = 'any' ]; then  		CARCH='any'  	fi  	pkgfile="$pkgdir/$pkgname-$pkgver-$pkgrel-${CARCH}${PKGEXT}"  	if [ ! -f "$pkgfile" ]; then -		die "$(gettext "could not find %s-%s-%s-%s%s - aborting")" $pkgname $pkgver $pkgrel $CARCH $PKGEXT -	fi - -	if check_force; then -		opt_force="--force" +		die "could not find %s-%s-%s-%s%s - aborting" $pkgname $pkgver $pkgrel $CARCH $PKGEXT  	fi -	repo-add "$pkgdb" $opt_force "$pkgfile" +	repo-add "$pkgdb" "$pkgfile"  else # DELETE  	fname="$(basename $option)"  	if [ "$fname" = "PKGBUILD" ]; then  		if [ ! -f "$option" ]; then -			die "$(gettext "%s not found")" $option +			die "%s not found" $option  		fi  		unset pkgname pkgver pkgrel options diff --git a/contrib/zsh_completion b/contrib/zsh_completion index 8dec06df..e1273184 100644 --- a/contrib/zsh_completion +++ b/contrib/zsh_completion @@ -6,7 +6,6 @@ typeset -A opt_args  # options for passing to _arguments: main pacman commands  _pacman_opts_commands=( -	'-A[Add a package to the system]'  	'-Q[Query the package database]'  	'-R[Remove a package from the system]'  	'-S[Synchronize packages]' @@ -29,7 +28,7 @@ _pacman_opts_common=(  	'--noscriptlet[Do not execute the install scriptlet if one exists]'  ) -# options for passing to _arguments: options for --add and --update commands +# options for passing to _arguments: options for --upgrade commands  _pacman_opts_pkgfile=(  	'-d[Skip dependency checks]'  	'-f[Overwrite conflicting files]' @@ -78,7 +77,6 @@ _pacman_opts_sync_actions=(  # options for passing to _arguments: options for --sync command  _pacman_opts_sync_modifiers=(  	'-d[Skip dependency checks]' -	'-e[Install dependencies only]'  	'-f[Overwrite conflicting files]'  	'-i[View package information]'  	'-l[List all packages in a repository]' @@ -91,15 +89,9 @@ _pacman_opts_sync_modifiers=(  	'*--ignoregroup[Ignore a group upgrade]:package group:  		_pacman_completions_all_groups'  	'--asdeps[Install packages as non-explicitly installed]' +	'--asexplicit[Install packages as explicitly installed]'  ) -# handles --action subcommand -_pacman_action_add() { -	_arguments -s : \ -		"$_pacman_opts_common[@]" \ -		"$_pacman_opts_pkgfile[@]" -} -  # handles --help subcommand  _pacman_action_help() {  	_arguments -s : \ @@ -290,7 +282,6 @@ _pacman_get_command() {  # main dispatcher  _pacman() {  	case $words[2] in -		-A*)  _pacman_action_add      ;;  		-Q*g*) # ipkg groups  			_arguments -s : \  				"$_pacman_opts_common[@]" \ diff --git a/doc/Doxyfile b/doc/Doxyfile index 5174c651..f287bbcd 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.5.2 +# Doxyfile 1.5.5  #---------------------------------------------------------------------------  # Project related configuration options @@ -28,7 +28,8 @@ FULL_PATH_NAMES        = NO  STRIP_FROM_PATH        =   STRIP_FROM_INC_PATH    =   SHORT_NAMES            = NO -JAVADOC_AUTOBRIEF      = NO +JAVADOC_AUTOBRIEF      = YES +QT_AUTOBRIEF           = NO  MULTILINE_CPP_IS_BRIEF = NO  DETAILS_AT_TOP         = NO  INHERIT_DOCS           = YES @@ -37,10 +38,14 @@ TAB_SIZE               = 4  ALIASES                =   OPTIMIZE_OUTPUT_FOR_C  = YES  OPTIMIZE_OUTPUT_JAVA   = NO +OPTIMIZE_FOR_FORTRAN   = NO +OPTIMIZE_OUTPUT_VHDL   = NO  BUILTIN_STL_SUPPORT    = NO  CPP_CLI_SUPPORT        = NO +SIP_SUPPORT            = NO  DISTRIBUTE_GROUP_DOC   = NO  SUBGROUPING            = YES +TYPEDEF_HIDES_STRUCT   = NO  #---------------------------------------------------------------------------  # Build related configuration options  #--------------------------------------------------------------------------- @@ -49,6 +54,7 @@ EXTRACT_PRIVATE        = NO  EXTRACT_STATIC         = NO  EXTRACT_LOCAL_CLASSES  = YES  EXTRACT_LOCAL_METHODS  = NO +EXTRACT_ANON_NSPACES   = NO  HIDE_UNDOC_MEMBERS     = NO  HIDE_UNDOC_CLASSES     = NO  HIDE_FRIEND_COMPOUNDS  = NO @@ -60,6 +66,7 @@ SHOW_INCLUDE_FILES     = YES  INLINE_INFO            = YES  SORT_MEMBER_DOCS       = YES  SORT_BRIEF_DOCS        = NO +SORT_GROUP_NAMES       = NO  SORT_BY_SCOPE_NAME     = NO  GENERATE_TODOLIST      = YES  GENERATE_TESTLIST      = YES @@ -126,6 +133,10 @@ HTML_FOOTER            =  HTML_STYLESHEET        =   HTML_ALIGN_MEMBERS     = YES  GENERATE_HTMLHELP      = NO +GENERATE_DOCSET        = NO +DOCSET_FEEDNAME        = "Doxygen generated docs" +DOCSET_BUNDLE_ID       = org.doxygen.Project +HTML_DYNAMIC_SECTIONS  = NO  CHM_FILE               =   HHC_LOCATION           =   GENERATE_CHI           = NO @@ -194,7 +205,9 @@ EXPAND_ONLY_PREDEF     = YES  SEARCH_INCLUDES        = YES  INCLUDE_PATH           = ../..  INCLUDE_FILE_PATTERNS  = *.h -PREDEFINED             = HAVE_CONFIG_H= SYMHIDDEN= SYMEXPORT= +PREDEFINED             = HAVE_CONFIG_H= \ +                         SYMHIDDEN= \ +                         SYMEXPORT=  EXPAND_AS_DEFINED      =   SKIP_FUNCTION_MACROS   = YES  #--------------------------------------------------------------------------- @@ -227,6 +240,7 @@ DOT_IMAGE_FORMAT       = png  DOT_PATH               =   DOTFILE_DIRS           =   DOT_GRAPH_MAX_NODES    = 50 +MAX_DOT_GRAPH_DEPTH    = 3  DOT_TRANSPARENT        = NO  DOT_MULTI_TARGETS      = NO  GENERATE_LEGEND        = YES diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index ac394729..aa870097 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -182,6 +182,9 @@ Options and Directives  	*emptydirs*;;  		Leave empty directories in packages. +	*zipman*;; +		Compress man pages with gzip. +  	*ccache*;;  		Allow the use of ccache during build. More useful in its negative  		form `!ccache` with select packages that have problems building diff --git a/doc/makepkg.conf.5.txt b/doc/makepkg.conf.5.txt index f6e4b382..113ad140 100644 --- a/doc/makepkg.conf.5.txt +++ b/doc/makepkg.conf.5.txt @@ -37,6 +37,9 @@ Options  	well; the download URL is placed on the end of the command. This is more  	flexible than the former `FTPAGENT` variable, as any protocol can have a  	download agent. Several examples are provided in the default makepkg.conf. +	All instances of `%u` will be replaced with the download URL. If present, +	instances of `%o` will be replaced with the local filename, plus a ``.part'' +	extension, which allows to do file resumes properly.  **CARCH=**"carch"::  	Specifies your computer architecture; possible values include such things @@ -94,8 +97,8 @@ Options  	running in the DistCC cluster. In addition, you will want to modify your  	`MAKEFLAGS`. -**OPTIONS=(**strip !docs libtool emptydirs**)**:: -	This array contains options that affect the default packaging. All four are +**OPTIONS=(**strip !docs libtool emptydirs zipman**)**:: +	This array contains options that affect the default packaging. They are  	equivalent to options that can be placed in the PKGBUILD; the defaults are  	shown here. All options should always be left in the array; to enable or  	disable an option simply remove or place an ``!'' at the front of the @@ -117,6 +120,9 @@ Options  	*emptydirs*;;  		Leave empty directories in packages. +	*zipman*;; +		Compress man pages with gzip. +  **INTEGRITY_CHECK=(**check1 ...**)**::  	File integrity checks to use. Multiple checks may be specified; this  	affects both generation and checking. The current valid options are: diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index f6eb69c3..a6bc3d9a 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -28,13 +28,6 @@ ends to be written (for instance, a GUI front end).  Operations  ---------- -*-A, \--add* (deprecated):: -	Add a package to the system. Either a URL or file path can be specified. -	The package will be uncompressed into the installation root and the -	database will be updated. The package will not be installed if another -	version is already installed. *NOTE*: please use '\--upgrade' in place of -	this option. -  *-Q, \--query*::  	Query the package database. This operation allows you to view installed  	packages and their files, as well as meta-information about individual @@ -86,11 +79,17 @@ You can also use `pacman -Su` to upgrade all packages that are out of date. See  Options  -------  *\--asdeps*:: -	Install packages non-explicitly; in other works, fake their install reason +	Install packages non-explicitly; in other words, fake their install reason  	to be installed as a dependency. This is useful for makepkg and other  	build from source tools that need to install dependencies before building  	the package. +*\--asexplicit*:: +	Install packages explicitly; in other words, fake their install reason to +	be explicitly installed. This is useful if you want to mark a dependency +	as explicitly installed so it will not be removed by the '\--recursive' +	remove operation. +  *-b, \--dbpath* <'path'>::  	Specify an alternative database location (a typical default is  	``/var/lib/pacman'').  This should not be used unless you know what you are @@ -226,7 +225,12 @@ Remove Options[[RO]]  	that (A) they are not required by other packages; and (B) they were not  	explicitly installed by the user. This operation is recursive and analogous  	to a backwards '\--sync' operation, and helps keep a clean system without -	orphans. +	orphans. If you want to omit condition (B), pass this option twice. + +*-u, \--unneeded*:: +	Removes the targets that are not required by any other packages. +	This is mostly useful when removing a group without using the '-c' option, +	to avoid breaking any dependencies.  Sync Options[[SO]] @@ -241,10 +245,9 @@ Sync Options[[SO]]  	packages that are no longer installed; use two to remove all packages  	from the cache. In both cases, you will have a yes or no option to  	remove packages and/or unused downloaded databases. - -*-e, \--dependsonly*:: -	Install all dependencies of a package, but not the specified package -	itself. This is pretty useless and we're not sure why it even exists. ++ +If you use a network shared cache, see the 'CleanMethod' option in +linkman:pacman.conf[5].  *-g, \--groups*::  	Display all the members for each package group specified. If no group diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index cb9d2c55..5514e2c0 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -40,6 +40,8 @@ Include = /etc/pacman.d/core  Server = file:///home/pkgs  -------- +*NOTE*: Each directive must be in CamelCase. If the case isn't respected, the directive +won't be recognized. For example. noupgrade or NOUPGRADE will not work.  Options  ------- @@ -117,6 +119,15 @@ Options  	These files refer to files in the package archive, so do not include the  	leading slash (the RootDir) when specifying them. +*CleanMethod =* KeepInstalled | KeepCurrent:: +	If set to `KeepInstalled` (the default), the '-Sc' operation will clean +	packages that are no longer installed (not present in the local database). +	If set to `KeepCurrent`, '-Sc' will clean outdated packages (not present in +	any sync database). +	The second behavior is useful when the package cache is shared among +	multiple machines, where the local databases are usually different, but the +	sync databases in use could be the same. +  *UseSyslog*::  	Log action messages through syslog(). This will insert log entries into  	``/var/log/messages'' or equivalent. diff --git a/doc/repo-add.8.txt b/doc/repo-add.8.txt index 5664949f..80faef46 100644 --- a/doc/repo-add.8.txt +++ b/doc/repo-add.8.txt @@ -16,7 +16,7 @@ repo-add - package database maintenance utility  Synopsis  -------- -repo-add <path-to-db> [--force] <package> ... +repo-add <path-to-db> <package> ...  repo-remove <path-to-db> <packagename> ... @@ -34,16 +34,6 @@ specified on the command line. Multiple packages to remove can be specified  on the command line. -Options -------- -*--force* (repo-add only):: -	Add a force entry to the sync database, which tells pacman to skip version -	number comparison and update the package regardless. This flag can be -	specified in the middle of the command line, with any packages listed -	before the flag being added as normal entries, and any specified after -	being marked as force upgrades. - -  See Also  --------  linkman:makepkg[8], linkman:pacman[8] diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index 4da4a63d..345194d3 100644 --- a/etc/makepkg.conf.in +++ b/etc/makepkg.conf.in @@ -8,11 +8,11 @@  #  #-- The download utilities that makepkg should use to acquire sources  #  Format: 'protocol::agent' -DLAGENTS=('ftp::/usr/bin/wget -c --passive-ftp -t 3 --waitretry=3' -          'http::/usr/bin/wget -c -t 3 --waitretry=3' -          'https::/usr/bin/wget -c -t 3 --waitretry=3 --no-check-certificate' -          'rsync::/usr/bin/rsync -z' -          'scp::/usr/bin/scp -C') +DLAGENTS=('ftp::/usr/bin/wget -c --passive-ftp -t 3 --waitretry=3 -O %o %u' +          'http::/usr/bin/wget -c -t 3 --waitretry=3 -O %o %u' +          'https::/usr/bin/wget -c -t 3 --waitretry=3 --no-check-certificate -O %o %u' +          'rsync::/usr/bin/rsync -z %u %o' +          'scp::/usr/bin/scp -C %u %o')  # Other common tools:  # /usr/bin/snarf @@ -58,15 +58,16 @@ BUILDENV=(fakeroot !distcc color !ccache !xdelta)  #   These are default values for the options=() settings  #########################################################################  # -# Default: OPTIONS=(strip !docs libtool emptydirs) +# Default: OPTIONS=(strip !docs libtool emptydirs zipman)  #  A negated option will do the opposite of the comments below.  #  #-- strip:     Strip symbols from binaries/libraries  #-- docs:      Save doc and info directories  #-- libtool:   Leave libtool (.la) files in packages  #-- emptydirs: Leave empty directories in packages +#-- zipman:    Compress manpages with gzip  # -OPTIONS=(strip !docs libtool emptydirs) +OPTIONS=(strip !docs libtool emptydirs zipman)  #-- File integrity checks to use. Valid: md5, sha1, sha256, sha384, sha512  INTEGRITY_CHECK=(md5) diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index 14d42a0c..7b737363 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -31,14 +31,15 @@ libalpm_la_SOURCES = \  	db.h db.c \  	delta.h delta.c \  	deps.h deps.c \ -	error.h error.c \ +	dload.h dload.c \ +	error.c \ +	graph.h \  	group.h group.c \  	handle.h handle.c \  	log.h log.c \  	md5.h md5.c \  	package.h package.c \  	remove.h remove.c \ -	server.h server.c \  	sync.h sync.c \  	trans.h trans.c \  	util.h util.c diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 0a1a1924..f759e7de 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -37,7 +37,6 @@  #include "alpm_list.h"  #include "trans.h"  #include "util.h" -#include "error.h"  #include "cache.h"  #include "log.h"  #include "backup.h" @@ -68,41 +67,25 @@ int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)  	pkgname = alpm_pkg_get_name(pkg);  	pkgver = alpm_pkg_get_version(pkg); -	if(trans->type != PM_TRANS_TYPE_UPGRADE) { -		/* only install this package if it is not already installed */ -		if(_alpm_db_get_pkgfromcache(db, pkgname)) { -			pm_errno = PM_ERR_PKG_INSTALLED; -			goto error; -		} -	} -  	/* check if an older version of said package is already in transaction  	 * packages.  if so, replace it in the list */  	for(i = trans->packages; i; i = i->next) { -		pmpkg_t *pkg = i->data; -		if(strcmp(pkg->name, pkgname) == 0) { -			if(_alpm_versioncmp(pkg->version, pkgver) < 0) { -				pmpkg_t *newpkg; +		pmpkg_t *transpkg = i->data; +		if(strcmp(transpkg->name, pkgname) == 0) { +			if(_alpm_versioncmp(transpkg->version, pkgver) < 0) {  				_alpm_log(PM_LOG_WARNING, _("replacing older version %s-%s by %s in target list\n"), -				          pkg->name, pkg->version, pkgver); -				if((newpkg = _alpm_pkg_load(name, 1)) == NULL) { -					/* pm_errno is already set by pkg_load() */ -					goto error; -				} +				          transpkg->name, transpkg->version, pkgver);  				_alpm_pkg_free(i->data); -				i->data = newpkg; +				i->data = pkg;  			} else { -				_alpm_log(PM_LOG_WARNING, _("newer version %s-%s is in the target list -- skipping\n"), -				          pkg->name, pkg->version); +				_alpm_log(PM_LOG_WARNING, _("skipping %s-%s because newer version %s is in the target list\n"), +				          pkgname, pkgver, transpkg->version); +				_alpm_pkg_free(pkg);  			}  			return(0);  		}  	} -	if(trans->flags & PM_TRANS_FLAG_ALLDEPS) { -		pkg->reason = PM_PKG_REASON_DEPEND; -	} -  	/* add the package to the transaction */  	trans->packages = alpm_list_add(trans->packages, pkg); @@ -138,12 +121,13 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)  		/* look for unsatisfied dependencies */  		_alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); -		lp = alpm_checkdeps(db, trans->type == PM_TRANS_TYPE_UPGRADE, NULL, trans->packages); +		lp = alpm_checkdeps(db, 1, NULL, trans->packages);  		if(lp != NULL) {  			if(data) {  				*data = lp;  			} else { -				FREELIST(lp); +				alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); +				alpm_list_free(lp);  			}  			RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1);  		} @@ -167,7 +151,7 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)  				_alpm_log(PM_LOG_ERROR, _("you cannot install two conflicting packages at the same time\n"));  			}  			if(outer) { -				_alpm_log(PM_LOG_ERROR, _("replacing packages with -A and -U is not supported yet\n")); +				_alpm_log(PM_LOG_ERROR, _("replacing packages with -U is not supported yet\n"));  				_alpm_log(PM_LOG_ERROR, _("you can replace packages manually using -Rd and -U\n"));  			}  			RET_ERR(PM_ERR_CONFLICTING_DEPS, -1); @@ -175,7 +159,7 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)  		/* re-order w.r.t. dependencies */  		_alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); -		lp = _alpm_sortbydeps(trans->packages, PM_TRANS_TYPE_ADD); +		lp = _alpm_sortbydeps(trans->packages, 0);  		/* free the old alltargs */  		alpm_list_free(trans->packages);  		trans->packages = lp; @@ -193,7 +177,8 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)  			if(data) {  				*data = lp;  			} else { -				FREELIST(lp); +				alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_fileconflict_free); +				alpm_list_free(lp);  			}  			RET_ERR(PM_ERR_FILE_CONFLICTS, -1);  		} @@ -210,6 +195,9 @@ static int upgrade_remove(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans, pm  	 * with the type PM_TRANS_TYPE_REMOVEUPGRADE. TODO: kill this weird  	 * behavior. */  	pmtrans_t *tr = _alpm_trans_new(); + +	ALPM_LOG_FUNC; +  	_alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n",  			oldpkg->name, oldpkg->version); @@ -437,7 +425,7 @@ static int extract_single_file(struct archive *archive,  				/* if we force hash_orig to be non-NULL retroactive backup works */  				if(needbackup && !hash_orig) { -					hash_orig = strdup(""); +					STRDUP(hash_orig, "", RET_ERR(PM_ERR_MEMORY, -1));  				}  			}  		} @@ -446,16 +434,14 @@ static int extract_single_file(struct archive *archive,  	}  	if(needbackup) { -		char *tempfile; +		char checkfile[PATH_MAX];  		char *hash_local = NULL, *hash_pkg = NULL; -		int fd; +		int ret; -		/* extract the package's version to a temporary file and checksum it */ -		tempfile = strdup("/tmp/alpm_XXXXXX"); -		fd = mkstemp(tempfile); +		snprintf(checkfile, PATH_MAX, "%s.paccheck", filename); +		archive_entry_set_pathname(entry, checkfile); -		int ret = archive_read_data_into_fd(archive, fd); -		close(fd); +		ret = archive_read_extract(archive, entry, archive_flags);  		if(ret == ARCHIVE_WARN) {  			/* operation succeeded but a non-critical error was encountered */  			_alpm_log(PM_LOG_DEBUG, "warning extracting %s (%s)\n", @@ -465,14 +451,12 @@ static int extract_single_file(struct archive *archive,  					entryname, archive_error_string(archive));  			alpm_logaction("error: could not extract %s (%s)\n",  					entryname, archive_error_string(archive)); -			unlink(tempfile); -			FREE(tempfile);  			FREE(hash_orig);  			return(1);  		}  		hash_local = alpm_get_md5sum(filename); -		hash_pkg = alpm_get_md5sum(tempfile); +		hash_pkg = alpm_get_md5sum(checkfile);  		/* append the new md5 hash to it's respective entry  		 * in newpkg's backup (it will be the new orginal) */ @@ -485,11 +469,8 @@ static int extract_single_file(struct archive *archive,  			}  			char *backup = NULL;  			/* length is tab char, null byte and MD5 (32 char) */ -			int backup_len = strlen(oldbackup) + 34; -			backup = malloc(backup_len); -			if(!backup) { -				RET_ERR(PM_ERR_MEMORY, -1); -			} +			size_t backup_len = strlen(oldbackup) + 34; +			MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1));  			sprintf(backup, "%s\t%s", oldbackup, hash_pkg);  			backup[backup_len-1] = '\0'; @@ -511,19 +492,20 @@ static int extract_single_file(struct archive *archive,  				/* move the existing file to the "pacorig" */  				if(rename(filename, newpath)) { -					archive_entry_set_pathname(entry, filename); -					_alpm_log(PM_LOG_ERROR, _("could not rename %s (%s)\n"), filename, strerror(errno)); -					alpm_logaction("error: could not rename %s (%s)\n", filename, strerror(errno)); +					_alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), +							filename, newpath, strerror(errno)); +					alpm_logaction("error: could not rename %s to %s (%s)\n", +							filename, newpath, strerror(errno));  					errors++;  				} else { -					/* copy the tempfile we extracted to the real path */ -					if(_alpm_copyfile(tempfile, filename)) { -						archive_entry_set_pathname(entry, filename); -						_alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), filename, strerror(errno)); -						alpm_logaction("error: could not copy tempfile to %s (%s)\n", filename, strerror(errno)); +					/* rename the file we extracted to the real name */ +					if(rename(checkfile, filename)) { +						_alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), +								checkfile, filename, strerror(errno)); +						alpm_logaction("error: could not rename %s to %s (%s)\n", +								checkfile, filename, strerror(errno));  						errors++;  					} else { -						archive_entry_set_pathname(entry, filename);  						_alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);  						alpm_logaction("warning: %s saved as %s\n", filename, newpath);  					} @@ -538,36 +520,45 @@ static int extract_single_file(struct archive *archive,  					_alpm_log(PM_LOG_DEBUG, "action: installing new file: %s\n",  							entryname); -					if(_alpm_copyfile(tempfile, filename)) { -						_alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), filename, strerror(errno)); +					if(rename(checkfile, filename)) { +						_alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), +								checkfile, filename, strerror(errno)); +						alpm_logaction("error: could not rename %s to %s (%s)\n", +								checkfile, filename, strerror(errno));  						errors++;  					} -					archive_entry_set_pathname(entry, filename);  				} else {  					/* there's no sense in installing the same file twice, install  					 * ONLY is the original and package hashes differ */  					_alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); +					unlink(checkfile);  				}  			} else if(strcmp(hash_orig, hash_pkg) == 0) {  				/* originally installed file and new file are the same - this  				 * implies the case above failed - i.e. the file was changed by a  				 * user */  				_alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); +				unlink(checkfile);  			} else if(strcmp(hash_local, hash_pkg) == 0) {  				/* this would be magical.  The above two cases failed, but the  				 * user changes just so happened to make the new file exactly the  				 * same as the one in the package... skip it */  				_alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); +				unlink(checkfile);  			} else {  				char newpath[PATH_MAX];  				_alpm_log(PM_LOG_DEBUG, "action: keeping current file and installing new one with .pacnew ending\n");  				snprintf(newpath, PATH_MAX, "%s.pacnew", filename); -				if(_alpm_copyfile(tempfile, newpath)) { -					_alpm_log(PM_LOG_ERROR, _("could not install %s as %s: %s\n"), filename, newpath, strerror(errno)); -					alpm_logaction("error: could not install %s as %s: %s\n", filename, newpath, strerror(errno)); +				if(rename(checkfile, newpath)) { +					_alpm_log(PM_LOG_ERROR, _("could not install %s as %s (%s)\n"), +							filename, newpath, strerror(errno)); +					alpm_logaction("error: could not install %s as %s (%s)\n", +							filename, newpath, strerror(errno));  				} else { -					_alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"), filename, newpath); -					alpm_logaction("warning: %s installed as %s\n", filename, newpath); +					_alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"), +							filename, newpath); +					alpm_logaction("warning: %s installed as %s\n", +							filename, newpath);  				}  			}  		} @@ -575,9 +566,9 @@ static int extract_single_file(struct archive *archive,  		FREE(hash_local);  		FREE(hash_pkg);  		FREE(hash_orig); -		unlink(tempfile); -		FREE(tempfile);  	} else { +		int ret; +  		/* we didn't need a backup */  		if(notouch) {  			/* change the path to a .pacnew extension */ @@ -598,7 +589,7 @@ static int extract_single_file(struct archive *archive,  		archive_entry_set_pathname(entry, filename); -		int ret = archive_read_extract(archive, entry, archive_flags); +		ret = archive_read_extract(archive, entry, archive_flags);  		if(ret == ARCHIVE_WARN) {  			/* operation succeeded but a non-critical error was encountered */  			_alpm_log(PM_LOG_DEBUG, "warning extracting %s (%s)\n", @@ -617,7 +608,7 @@ static int extract_single_file(struct archive *archive,  			char *backup = NULL, *hash = NULL;  			char *oldbackup = alpm_list_getdata(b);  			/* length is tab char, null byte and MD5 (32 char) */ -			int backup_len = strlen(oldbackup) + 34; +			size_t backup_len = strlen(oldbackup) + 34;  			if(!oldbackup || strcmp(oldbackup, entryname) != 0) {  				continue; @@ -625,10 +616,7 @@ static int extract_single_file(struct archive *archive,  			_alpm_log(PM_LOG_DEBUG, "appending backup entry for %s\n", filename);  			hash = alpm_get_md5sum(filename); -			backup = malloc(backup_len); -			if(!backup) { -				RET_ERR(PM_ERR_MEMORY, -1); -			} +			MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1));  			sprintf(backup, "%s\t%s", oldbackup, hash);  			backup[backup_len-1] = '\0'; @@ -644,14 +632,13 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,  		pmtrans_t *trans, pmdb_t *db)  {  	int i, ret = 0, errors = 0; -	struct archive *archive; -	struct archive_entry *entry; -	char cwd[PATH_MAX] = "";  	char scriptlet[PATH_MAX+1];  	int is_upgrade = 0;  	double percent = 0.0;  	pmpkg_t *oldpkg = NULL; +	ALPM_LOG_FUNC; +  	snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path,  			alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); @@ -666,12 +653,8 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,  		/* we'll need to save some record for backup checks later */  		oldpkg = _alpm_pkg_dup(local); -		/* copy over the install reason (unless alldeps is set) */ -	if(trans->flags & PM_TRANS_FLAG_ALLDEPS) { -		newpkg->reason = PM_PKG_REASON_DEPEND; -	} else { +		/* copy over the install reason */  		newpkg->reason = alpm_pkg_get_reason(local); -	}  		/* pre_upgrade scriptlet */  		if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { @@ -692,6 +675,13 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,  		}  	} +	/* we override any pre-set reason if we have alldeps or allexplicit set */ +	if(trans->flags & PM_TRANS_FLAG_ALLDEPS) { +		newpkg->reason = PM_PKG_REASON_DEPEND; +	} else if(trans->flags & PM_TRANS_FLAG_ALLEXPLICIT) { +		newpkg->reason = PM_PKG_REASON_EXPLICIT; +	} +  	if(oldpkg) {  		/* set up fake remove transaction */  		int ret = upgrade_remove(oldpkg, newpkg, trans, db); @@ -701,15 +691,20 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,  	}  	if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) { +		struct archive *archive; +		struct archive_entry *entry; +		char cwd[PATH_MAX] = ""; +  		_alpm_log(PM_LOG_DEBUG, "extracting files\n");  		if ((archive = archive_read_new()) == NULL) { -			RET_ERR(PM_ERR_LIBARCHIVE_ERROR, -1); +			RET_ERR(PM_ERR_LIBARCHIVE, -1);  		}  		archive_read_support_compression_all(archive);  		archive_read_support_format_all(archive); +		_alpm_log(PM_LOG_DEBUG, "archive: %s\n", newpkg->origin_data.file);  		if(archive_read_open_filename(archive, newpkg->origin_data.file,  					ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {  			RET_ERR(PM_ERR_PKG_OPEN, -1); @@ -850,7 +845,7 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)  		return(0);  	} -	pkg_count = alpm_list_count(trans->targets); +	pkg_count = alpm_list_count(trans->packages);  	pkg_current = 1;  	/* loop through our package list adding/upgrading one at a time */ diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index fb19d076..ee29d534 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -25,7 +25,6 @@  /* libalpm */  #include "alpm.h"  #include "alpm_list.h" -#include "error.h"  #include "handle.h"  #include "util.h" diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 96b63ca6..c6d11a5f 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -45,14 +45,12 @@ typedef struct __pmdb_t pmdb_t;  typedef struct __pmpkg_t pmpkg_t;  typedef struct __pmdelta_t pmdelta_t;  typedef struct __pmgrp_t pmgrp_t; -typedef struct __pmserver_t pmserver_t;  typedef struct __pmtrans_t pmtrans_t;  typedef struct __pmsyncpkg_t pmsyncpkg_t;  typedef struct __pmdepend_t pmdepend_t;  typedef struct __pmdepmissing_t pmdepmissing_t;  typedef struct __pmconflict_t pmconflict_t;  typedef struct __pmfileconflict_t pmfileconflict_t; -typedef struct __pmgraph_t pmgraph_t;  /*   * Library @@ -81,8 +79,7 @@ int alpm_logaction(char *fmt, ...);   * Downloading   */ -typedef void (*alpm_cb_download)(const char *filename, int file_xfered, -		int file_total, int list_xfered, int list_total); +typedef void (*alpm_cb_download)(const char *filename, int xfered, int total);  /*   * Options @@ -225,38 +222,33 @@ size_t alpm_pkg_changelog_read(void *ptr, size_t size,  int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp);  unsigned short alpm_pkg_has_scriptlet(pmpkg_t *pkg); -unsigned long alpm_pkg_download_size(pmpkg_t *newpkg, pmdb_t *db_local); +unsigned long alpm_pkg_download_size(pmpkg_t *newpkg);  /*   * Deltas   */  const char *alpm_delta_get_from(pmdelta_t *delta); +const char *alpm_delta_get_from_md5sum(pmdelta_t *delta);  const char *alpm_delta_get_to(pmdelta_t *delta); -unsigned long alpm_delta_get_size(pmdelta_t *delta); +const char *alpm_delta_get_to_md5sum(pmdelta_t *delta);  const char *alpm_delta_get_filename(pmdelta_t *delta);  const char *alpm_delta_get_md5sum(pmdelta_t *delta); +unsigned long alpm_delta_get_size(pmdelta_t *delta);  /*   * Groups   */  const char *alpm_grp_get_name(const pmgrp_t *grp); -const alpm_list_t *alpm_grp_get_pkgs(const pmgrp_t *grp); +alpm_list_t *alpm_grp_get_pkgs(const pmgrp_t *grp);  /*   * Sync   */ -/* Types */ -typedef enum _pmsynctype_t { -	PM_SYNC_TYPE_REPLACE = 1, -	PM_SYNC_TYPE_UPGRADE, -	PM_SYNC_TYPE_DEPEND -} pmsynctype_t; - -pmsynctype_t alpm_sync_get_type(const pmsyncpkg_t *sync);  pmpkg_t *alpm_sync_get_pkg(const pmsyncpkg_t *sync); -void *alpm_sync_get_data(const pmsyncpkg_t *sync); +alpm_list_t *alpm_sync_get_removes(const pmsyncpkg_t *sync); +pmpkg_t *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync);  int alpm_sync_sysupgrade(pmdb_t *db_local,  		alpm_list_t *dbs_sync, alpm_list_t **syncpkgs); @@ -266,10 +258,9 @@ int alpm_sync_sysupgrade(pmdb_t *db_local,  /* Types */  typedef enum _pmtranstype_t { -	PM_TRANS_TYPE_ADD = 1, +	PM_TRANS_TYPE_UPGRADE = 1,  	PM_TRANS_TYPE_REMOVE,  	PM_TRANS_TYPE_REMOVEUPGRADE, -	PM_TRANS_TYPE_UPGRADE,  	PM_TRANS_TYPE_SYNC  } pmtranstype_t; @@ -282,45 +273,105 @@ typedef enum _pmtransflag_t {  	PM_TRANS_FLAG_CASCADE = 0x10,  	PM_TRANS_FLAG_RECURSE = 0x20,  	PM_TRANS_FLAG_DBONLY = 0x40, -	PM_TRANS_FLAG_DEPENDSONLY = 0x80, +	/* 0x80 flag can go here */  	PM_TRANS_FLAG_ALLDEPS = 0x100,  	PM_TRANS_FLAG_DOWNLOADONLY = 0x200,  	PM_TRANS_FLAG_NOSCRIPTLET = 0x400,  	PM_TRANS_FLAG_NOCONFLICTS = 0x800,  	PM_TRANS_FLAG_PRINTURIS = 0x1000, -	PM_TRANS_FLAG_NEEDED = 0x2000 +	PM_TRANS_FLAG_NEEDED = 0x2000, +	PM_TRANS_FLAG_ALLEXPLICIT = 0x4000, +	PM_TRANS_FLAG_UNNEEDED = 0x8000, +	PM_TRANS_FLAG_RECURSEALL = 0x10000  } pmtransflag_t; -/* Transaction Events */ +/** + * @addtogroup alpm_trans + * @{ + */ +/** + * @brief Transaction events. + * NULL parameters are passed to in all events unless specified otherwise. + */  typedef enum _pmtransevt_t { +	/** Dependencies will be computed for a package. */  	PM_TRANS_EVT_CHECKDEPS_START = 1, +	/** Dependencies were computed for a package. */  	PM_TRANS_EVT_CHECKDEPS_DONE, +	/** File conflicts will be computed for a package. */  	PM_TRANS_EVT_FILECONFLICTS_START, +	/** File conflicts were computed for a package. */  	PM_TRANS_EVT_FILECONFLICTS_DONE, +	/** Dependencies will be resolved for target package. */  	PM_TRANS_EVT_RESOLVEDEPS_START, +	/** Dependencies were resolved for target package. */  	PM_TRANS_EVT_RESOLVEDEPS_DONE, +	/** Inter-conflicts will be checked for target package. */  	PM_TRANS_EVT_INTERCONFLICTS_START, +	/** Inter-conflicts were checked for target package. */  	PM_TRANS_EVT_INTERCONFLICTS_DONE, +	/** Package will be installed. +	 * A pointer to the target package is passed to the callback. +	 */  	PM_TRANS_EVT_ADD_START, +	/** Package was installed. +	 * A pointer to the new package is passed to the callback. +	 */  	PM_TRANS_EVT_ADD_DONE, +	/** Package will be removed. +	 * A pointer to the target package is passed to the callback. +	 */  	PM_TRANS_EVT_REMOVE_START, +	/** Package was removed. +	 * A pointer to the removed package is passed to the callback. +	 */  	PM_TRANS_EVT_REMOVE_DONE, +	/** Package will be upgraded. +	 * A pointer to the upgraded package is passed to the callback. +	 */  	PM_TRANS_EVT_UPGRADE_START, +	/** Package was upgraded. +	 * A pointer to the new package, and a pointer to the old package is passed +	 * to the callback, respectively. +	 */  	PM_TRANS_EVT_UPGRADE_DONE, +	/** Package was extracted. */  	PM_TRANS_EVT_EXTRACT_DONE, +	/** Target package's integrity will be checked. */  	PM_TRANS_EVT_INTEGRITY_START, +	/** Target package's integrity was checked. */  	PM_TRANS_EVT_INTEGRITY_DONE, +	/** Target deltas's integrity will be checked. */  	PM_TRANS_EVT_DELTA_INTEGRITY_START, +	/** Target delta's integrity was checked. */  	PM_TRANS_EVT_DELTA_INTEGRITY_DONE, +	/** Deltas will be applied to packages. */  	PM_TRANS_EVT_DELTA_PATCHES_START, +	/** Deltas were applied to packages. */  	PM_TRANS_EVT_DELTA_PATCHES_DONE, +	/** Delta patch will be applied to target package. +	 * The filename of the package and the filename of the patch is passed to the +	 * callback. +	 */  	PM_TRANS_EVT_DELTA_PATCH_START, +	/** Delta patch was applied to target package. */  	PM_TRANS_EVT_DELTA_PATCH_DONE, +	/** Delta patch failed to apply to target package. */  	PM_TRANS_EVT_DELTA_PATCH_FAILED, +	/** Scriptlet has printed information. +	 * A line of text is passed to the callback. +	 */  	PM_TRANS_EVT_SCRIPTLET_INFO, +	/** Print URI. +	 * The database's URI and the package's filename are passed to the callback. +	 */  	PM_TRANS_EVT_PRINTURI, +	/** Files will be downloaded from a repository. +	 * The repository's tree name is passed to the callback. +	 */  	PM_TRANS_EVT_RETRIEVE_START,  } pmtransevt_t; +/*@}*/  /* Transaction Conversations (ie, questions) */  typedef enum _pmtransconv_t { @@ -353,7 +404,6 @@ typedef void (*alpm_trans_cb_progress)(pmtransprog_t, const char *, int, int, in  pmtranstype_t alpm_trans_get_type();  unsigned int alpm_trans_get_flags(); -alpm_list_t * alpm_trans_get_targets();  alpm_list_t * alpm_trans_get_pkgs();  int alpm_trans_init(pmtranstype_t type, pmtransflag_t flags,                      alpm_trans_cb_event cb_event, alpm_trans_cb_conv conv, @@ -378,13 +428,16 @@ typedef enum _pmdepmod_t {  	PM_DEP_MOD_LT  } pmdepmod_t; -pmdepend_t *alpm_splitdep(const char *depstring);  int alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep);  alpm_list_t *alpm_checkdeps(pmdb_t *db, int reversedeps,  		alpm_list_t *remove, alpm_list_t *upgrade); +alpm_list_t *alpm_deptest(pmdb_t *db, alpm_list_t *targets);  const char *alpm_miss_get_target(const pmdepmissing_t *miss);  pmdepend_t *alpm_miss_get_dep(pmdepmissing_t *miss); +const char *alpm_miss_get_causingpkg(const pmdepmissing_t *miss); + +alpm_list_t *alpm_checkdbconflicts(pmdb_t *db_local);  const char *alpm_conflict_get_package1(pmconflict_t *conflict);  const char *alpm_conflict_get_package2(pmconflict_t *conflict); @@ -439,12 +492,6 @@ enum _pmerrno_t {  	PM_ERR_DB_REMOVE,  	/* Servers */  	PM_ERR_SERVER_BAD_URL, -	/* Configuration */ -	PM_ERR_OPT_LOGFILE, -	PM_ERR_OPT_DBPATH, -	PM_ERR_OPT_LOCALDB, -	PM_ERR_OPT_SYNCDB, -	PM_ERR_OPT_USESYSLOG,  	/* Transactions */  	PM_ERR_TRANS_NOT_NULL,  	PM_ERR_TRANS_NULL, @@ -460,14 +507,12 @@ enum _pmerrno_t {  	PM_ERR_PKG_INVALID,  	PM_ERR_PKG_OPEN,  	PM_ERR_PKG_LOAD, -	PM_ERR_PKG_INSTALLED,  	PM_ERR_PKG_CANT_FRESH,  	PM_ERR_PKG_CANT_REMOVE,  	PM_ERR_PKG_INVALID_NAME, -	PM_ERR_PKG_CORRUPTED,  	PM_ERR_PKG_REPO_NOT_FOUND,  	/* Deltas */ -	PM_ERR_DLT_CORRUPTED, +	PM_ERR_DLT_INVALID,  	PM_ERR_DLT_PATCHFAILED,  	/* Groups */  	PM_ERR_GRP_NOT_FOUND, @@ -478,14 +523,14 @@ enum _pmerrno_t {  	/* Misc */  	PM_ERR_USER_ABORT,  	PM_ERR_INTERNAL_ERROR, -	PM_ERR_LIBARCHIVE_ERROR,  	PM_ERR_DB_SYNC,  	PM_ERR_RETRIEVE,  	PM_ERR_PKG_HOLD,  	PM_ERR_INVALID_REGEX, -  /* Downloading */ -	PM_ERR_CONNECT_FAILED, -  PM_ERR_FORK_FAILED +	/* External library errors */ +	PM_ERR_LIBARCHIVE, +	PM_ERR_LIBDOWNLOAD, +	PM_ERR_EXTERNAL_DOWNLOAD  };  extern enum _pmerrno_t pm_errno; diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 57c8376a..ae54e190 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -1,7 +1,7 @@  /*   *  alpm_list.c   * - *  Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> + *  Copyright (c) 2002-2008 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -17,15 +17,16 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdlib.h>  #include <string.h>  #include <stdio.h>  /* libalpm */  #include "alpm_list.h" -#include "util.h" + +/* check exported library symbols with: nm -C -D <lib> */ +#define SYMEXPORT __attribute__((visibility("default"))) +#define SYMHIDDEN __attribute__((visibility("internal")))  /**   * @addtogroup alpm_list List Functions @@ -40,25 +41,6 @@  /* Allocation */  /** - * @brief Allocate a new alpm_list_t. - * - * @return a new alpm_list_t item, or NULL on failure - */ -alpm_list_t SYMEXPORT *alpm_list_new() -{ -	alpm_list_t *list = NULL; - -	list = malloc(sizeof(alpm_list_t)); -	if(list) { -		list->data = NULL; -		list->prev = list; /* maintain a back reference to the tail pointer */ -		list->next = NULL; -	} - -	return(list); -} - -/**   * @brief Free a list, but not the contained data.   *   * @param list the list to free @@ -107,30 +89,26 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data)  {  	alpm_list_t *ptr, *lp; -	ptr = list; +	ptr = calloc(1, sizeof(alpm_list_t));  	if(ptr == NULL) { -		ptr = alpm_list_new(); -		if(ptr == NULL) { -			return(NULL); -		} +		return(list);  	} -	lp = alpm_list_last(ptr); -	if(lp == ptr && lp->data == NULL) { -		/* nada */ -	} else { -		lp->next = alpm_list_new(); -		if(lp->next == NULL) { -			return(NULL); -		} -		lp->next->prev = lp; -		lp = lp->next; -		list->prev = lp; +	ptr->data = data; +	ptr->next = NULL; + +	/* Special case: the input list is empty */ +	if(list == NULL) { +		ptr->prev = ptr; +		return(ptr);  	} -	lp->data = data; +	lp = alpm_list_last(list); +	lp->next = ptr; +	ptr->prev = lp; +	list->prev = ptr; -	return(ptr); +	return(list);  }  /** @@ -144,12 +122,15 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data)   */  alpm_list_t SYMEXPORT *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_list_fn_cmp fn)  { -	if(!fn) { -		return alpm_list_add(list, data); +	if(!fn || !list) { +		return(alpm_list_add(list, data));  	} else {  		alpm_list_t *add = NULL, *prev = NULL, *next = list; -		add = alpm_list_new(); +		add = calloc(1, sizeof(alpm_list_t)); +		if(add == NULL) { +			return(list); +		}  		add->data = data;  		/* Find insertion point. */ @@ -159,26 +140,25 @@ alpm_list_t SYMEXPORT *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_  			next = next->next;  		} -		/*  Insert node before insertion point. */ -		add->prev = prev; -		add->next = next; - -		if(next != NULL) { -			next->prev = add;   /*  Not at end.  */ -		} - -		if(prev != NULL) { -			prev->next = add;       /*  In middle.  */ -		} else { -			list = add; /* At beginning, or new list */ -		} - -		if(next == NULL) { -			/* At end, adjust tail pointer on head node */ +		/* Insert the add node to the list */ +		if(prev == NULL) { /* special case: we insert add as the first element */ +			add->prev = list->prev; /* list != NULL */ +			add->next = list; +			list->prev = add; +			return(add); +		} else if(next == NULL) { /* another special case: add last element */ +			add->prev = prev; +			add->next = NULL; +			prev->next = add;  			list->prev = add; +			return(list); +		} else { +			add->prev = prev; +			add->next = next; +			next->prev = add; +			prev->next = add; +			return(list);  		} - -		return(list);  	}  } @@ -198,10 +178,10 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second)  	alpm_list_t *tmp;  	if (first == NULL) { -		return second; +		return(second);  	}  	if (second == NULL) { -		return first; +		return(first);  	}  	/* tmp is the last element of the first list */  	tmp = first->prev; @@ -464,18 +444,22 @@ alpm_list_t SYMEXPORT *alpm_list_copy_data(const alpm_list_t *list,  alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list)  {  	const alpm_list_t *lp; -	alpm_list_t *newlist = NULL; +	alpm_list_t *newlist = NULL, *backup; -	lp = alpm_list_last(list); -	if(list) { -		/* break our reverse circular list */ -		list->prev = NULL; +	if(list == NULL) { +		return(NULL);  	} +	lp = alpm_list_last(list); +	/* break our reverse circular list */ +	backup = list->prev; +	list->prev = NULL; +  	while(lp) {  		newlist = alpm_list_add(newlist, lp->data);  		lp = lp->prev;  	} +	list->prev = backup; /* restore tail pointer */  	return(newlist);  } @@ -490,14 +474,18 @@ alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list)   */  inline alpm_list_t SYMEXPORT *alpm_list_first(const alpm_list_t *list)  { -	return((alpm_list_t*)list); +	if(list) { +		return((alpm_list_t*)list); +	} else { +		return(NULL); +	}  }  /**   * @brief Return nth element from list (starting from 0).   *   * @param list the list - * @param n    the index of the item to find + * @param n    the index of the item to find (n < alpm_list_count(list) IS needed)   *   * @return an alpm_list_t node for index `n`   */ @@ -519,7 +507,11 @@ alpm_list_t SYMEXPORT *alpm_list_nth(const alpm_list_t *list, int n)   */  inline alpm_list_t SYMEXPORT *alpm_list_next(const alpm_list_t *node)  { -	return(node->next); +	if(node) { +		return(node->next); +	} else { +		return(NULL); +	}  }  /** diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index ae373910..b3846ba0 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -19,6 +19,8 @@  #ifndef _ALPM_LIST_H  #define _ALPM_LIST_H +#include <stdlib.h> /* size_t */ +  #ifdef __cplusplus  extern "C" {  #endif @@ -45,7 +47,6 @@ typedef void (*alpm_list_fn_free)(void *); /* item deallocation callback */  typedef int (*alpm_list_fn_cmp)(const void *, const void *); /* item comparison callback */  /* allocation */ -alpm_list_t *alpm_list_new(void);  void alpm_list_free(alpm_list_t *list);  void alpm_list_free_inner(alpm_list_t *list, alpm_list_fn_free fn); diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c index 4cd0985e..7cc01c26 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -39,7 +39,6 @@  #include "log.h"  #include "util.h"  #include "alpm.h" -#include "error.h"  #include "handle.h"  #include "package.h"  #include "delta.h" @@ -106,7 +105,7 @@ void _alpm_db_rewind(pmdb_t *db)  	rewinddir(db->handle);  } -static int _alpm_db_splitname(const char *target, char *name, char *version) +static int splitname(const char *target, pmpkg_t *pkg)  {  	/* the format of a db entry is as follows:  	 *    package-version-rel/ @@ -115,10 +114,10 @@ static int _alpm_db_splitname(const char *target, char *name, char *version)  	 */  	char *tmp, *p, *q; -	if(target == NULL) { +	if(target == NULL || pkg == NULL) {  		return(-1);  	} -	tmp = strdup(target); +	STRDUP(tmp, target, RET_ERR(PM_ERR_MEMORY, -1));  	p = tmp + strlen(tmp);  	/* do the magic parsing- find the beginning of the version string @@ -130,14 +129,16 @@ static int _alpm_db_splitname(const char *target, char *name, char *version)  	}  	/* copy into fields and return */ -	if(version) { -		strncpy(version, p+1, PKG_VERSION_LEN); +	if(pkg->version) { +		FREE(pkg->version);  	} +	STRDUP(pkg->version, p+1, RET_ERR(PM_ERR_MEMORY, -1));  	/* insert a terminator at the end of the name (on hyphen)- then copy it */  	*p = '\0'; -	if(name) { -		strncpy(name, tmp, PKG_NAME_LEN); +	if(pkg->name) { +		FREE(pkg->name);  	} +	STRDUP(pkg->name, tmp, RET_ERR(PM_ERR_MEMORY, -1));  	free(tmp);  	return(0); @@ -148,7 +149,6 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)  	struct dirent *ent = NULL;  	struct stat sbuf;  	char path[PATH_MAX]; -	char name[PKG_FULLNAME_LEN];  	char *ptr = NULL;  	int found = 0;  	pmpkg_t *pkg = NULL; @@ -168,7 +168,9 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)  			/* search for a specific package (by name only) */  			rewinddir(db->handle);  			while(!found && (ent = readdir(db->handle)) != NULL) { -				if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { +				char *name; + +				if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {  					continue;  				}  				/* stat the entry, make sure it's a directory */ @@ -176,7 +178,9 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)  				if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) {  					continue;  				} -				strncpy(name, ent->d_name, PKG_FULLNAME_LEN); + +				STRDUP(name, ent->d_name, return(NULL)); +  				/* truncate the string at the second-to-last hyphen, */  				/* which will give us the package name */  				if((ptr = rindex(name, '-'))) { @@ -185,10 +189,12 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)  				if((ptr = rindex(name, '-'))) {  					*ptr = '\0';  				} -				if(!strcmp(name, target)) { +				if(strcmp(name, target) == 0) {  					found = 1;  				} +				FREE(name);  			} +  			if(!found) {  				return(NULL);  			} @@ -199,7 +205,7 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)  				if(ent == NULL) {  					return(NULL);  				} -				if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { +				if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {  					isdir = 0;  					continue;  				} @@ -217,7 +223,7 @@ pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target)  			return(NULL);  		}  		/* split the db entry name */ -		if(_alpm_db_splitname(ent->d_name, pkg->name, pkg->version) != 0) { +		if(splitname(ent->d_name, pkg) != 0) {  			_alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"),  					ent->d_name);  			alpm_pkg_free(pkg); @@ -251,7 +257,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  		RET_ERR(PM_ERR_DB_NULL, -1);  	} -	if(info == NULL || info->name[0] == 0 || info->version[0] == 0) { +	if(info == NULL || info->name == NULL || info->version == NULL) {  		_alpm_log(PM_LOG_DEBUG, "invalid package entry provided to _alpm_db_read, skipping\n");  		return(-1);  	} @@ -296,120 +302,115 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  				break;  			}  			_alpm_strtrim(line); -			if(!strcmp(line, "%FILENAME%")) { -				if(fgets(info->filename, sizeof(info->filename), fp) == NULL) { +			if(strcmp(line, "%FILENAME%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(info->filename); -		  } else if(!strcmp(line, "%DESC%")) { -				if(fgets(info->desc, sizeof(info->desc), fp) == NULL) { +				STRDUP(info->filename, _alpm_strtrim(line), goto error); +		  } else if(strcmp(line, "%DESC%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(info->desc); -			} else if(!strcmp(line, "%GROUPS%")) { +				STRDUP(info->desc, _alpm_strtrim(line), goto error); +			} else if(strcmp(line, "%GROUPS%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->groups = alpm_list_add(info->groups, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->groups = alpm_list_add(info->groups, linedup);  				} -			} else if(!strcmp(line, "%URL%")) { -				if(fgets(info->url, sizeof(info->url), fp) == NULL) { +			} else if(strcmp(line, "%URL%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(info->url); -			} else if(!strcmp(line, "%LICENSE%")) { +				STRDUP(info->url, _alpm_strtrim(line), goto error); +			} else if(strcmp(line, "%LICENSE%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->licenses = alpm_list_add(info->licenses, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->licenses = alpm_list_add(info->licenses, linedup);  				} -			} else if(!strcmp(line, "%ARCH%")) { -				if(fgets(info->arch, sizeof(info->arch), fp) == NULL) { +			} else if(strcmp(line, "%ARCH%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(info->arch); -			} else if(!strcmp(line, "%BUILDDATE%")) { -				char tmp[32]; -				if(fgets(tmp, sizeof(tmp), fp) == NULL) { +				STRDUP(info->arch, _alpm_strtrim(line), goto error); +			} else if(strcmp(line, "%BUILDDATE%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(tmp); +				_alpm_strtrim(line); -				char first = tolower(tmp[0]); +				char first = tolower(line[0]);  				if(first > 'a' && first < 'z') {  					struct tm tmp_tm = {0}; //initialize to null incase of failure  					setlocale(LC_TIME, "C"); -					strptime(tmp, "%a %b %e %H:%M:%S %Y", &tmp_tm); +					strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);  					info->builddate = mktime(&tmp_tm);  					setlocale(LC_TIME, "");  				} else { -					info->builddate = atol(tmp); +					info->builddate = atol(line);  				} -			} else if(!strcmp(line, "%INSTALLDATE%")) { -				char tmp[32]; -				if(fgets(tmp, sizeof(tmp), fp) == NULL) { +			} else if(strcmp(line, "%INSTALLDATE%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(tmp); +				_alpm_strtrim(line); -				char first = tolower(tmp[0]); +				char first = tolower(line[0]);  				if(first > 'a' && first < 'z') {  					struct tm tmp_tm = {0}; //initialize to null incase of failure  					setlocale(LC_TIME, "C"); -					strptime(tmp, "%a %b %e %H:%M:%S %Y", &tmp_tm); +					strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);  					info->installdate = mktime(&tmp_tm);  					setlocale(LC_TIME, "");  				} else { -					info->installdate = atol(tmp); +					info->installdate = atol(line);  				} -			} else if(!strcmp(line, "%PACKAGER%")) { -				if(fgets(info->packager, sizeof(info->packager), fp) == NULL) { +			} else if(strcmp(line, "%PACKAGER%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(info->packager); -			} else if(!strcmp(line, "%REASON%")) { -				char tmp[32]; -				if(fgets(tmp, sizeof(tmp), fp) == NULL) { +				STRDUP(info->packager, _alpm_strtrim(line), goto error); +			} else if(strcmp(line, "%REASON%") == 0) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(tmp); -				info->reason = atol(tmp); -			} else if(!strcmp(line, "%SIZE%") || !strcmp(line, "%CSIZE%")) { +				info->reason = atol(_alpm_strtrim(line)); +			} else if(strcmp(line, "%SIZE%") == 0 || strcmp(line, "%CSIZE%") == 0) {  				/* NOTE: the CSIZE and SIZE fields both share the "size" field  				 *       in the pkginfo_t struct.  This can be done b/c CSIZE  				 *       is currently only used in sync databases, and SIZE is  				 *       only used in local databases.  				 */ -				char tmp[32]; -				if(fgets(tmp, sizeof(tmp), fp) == NULL) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(tmp); -				info->size = atol(tmp); +				info->size = atol(_alpm_strtrim(line));  				/* also store this value to isize if isize is unset */  				if(info->isize == 0) { -					info->isize = atol(tmp); +					info->isize = info->size;  				} -			} else if(!strcmp(line, "%ISIZE%")) { +			} else if(strcmp(line, "%ISIZE%") == 0) {  				/* ISIZE (installed size) tag only appears in sync repositories,  				 * not the local one. */ -				char tmp[32]; -				if(fgets(tmp, sizeof(tmp), fp) == NULL) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -				_alpm_strtrim(tmp); -				info->isize = atol(tmp); -			} else if(!strcmp(line, "%MD5SUM%")) { +				info->isize = atol(_alpm_strtrim(line)); +			} else if(strcmp(line, "%MD5SUM%") == 0) {  				/* MD5SUM tag only appears in sync repositories,  				 * not the local one. */ -				if(fgets(info->md5sum, sizeof(info->md5sum), fp) == NULL) { +				if(fgets(line, 512, fp) == NULL) {  					goto error;  				} -			} else if(!strcmp(line, "%REPLACES%")) { -				/* the REPLACES tag is special -- it only appears in sync repositories, -				 * not the local one. */ +				STRDUP(info->md5sum, _alpm_strtrim(line), goto error); +			} else if(strcmp(line, "%REPLACES%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->replaces = alpm_list_add(info->replaces, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->replaces = alpm_list_add(info->replaces, linedup);  				} -			} else if(!strcmp(line, "%FORCE%")) { -				/* FORCE tag only appears in sync repositories, -				 * not the local one. */ +			} else if(strcmp(line, "%FORCE%") == 0) {  				info->force = 1;  			}  		} @@ -426,13 +427,17 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  		}  		while(fgets(line, 256, fp)) {  			_alpm_strtrim(line); -			if(!strcmp(line, "%FILES%")) { +			if(strcmp(line, "%FILES%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->files = alpm_list_add(info->files, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->files = alpm_list_add(info->files, linedup);  				} -			} else if(!strcmp(line, "%BACKUP%")) { +			} else if(strcmp(line, "%BACKUP%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->backup = alpm_list_add(info->backup, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->backup = alpm_list_add(info->backup, linedup);  				}  			}  		} @@ -450,37 +455,30 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  		while(!feof(fp)) {  			fgets(line, 255, fp);  			_alpm_strtrim(line); -			if(!strcmp(line, "%DEPENDS%")) { +			if(strcmp(line, "%DEPENDS%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					pmdepend_t *dep = alpm_splitdep(line); +					pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line));  					info->depends = alpm_list_add(info->depends, dep);  				} -			} else if(!strcmp(line, "%OPTDEPENDS%")) { +			} else if(strcmp(line, "%OPTDEPENDS%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->optdepends = alpm_list_add(info->optdepends, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->optdepends = alpm_list_add(info->optdepends, linedup);  				} -			} else if(!strcmp(line, "%CONFLICTS%")) { +			} else if(strcmp(line, "%CONFLICTS%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->conflicts = alpm_list_add(info->conflicts, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->conflicts = alpm_list_add(info->conflicts, linedup);  				} -			} else if(!strcmp(line, "%PROVIDES%")) { +			} else if(strcmp(line, "%PROVIDES%") == 0) {  				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->provides = alpm_list_add(info->provides, strdup(line)); +					char *linedup; +					STRDUP(linedup, _alpm_strtrim(line), goto error); +					info->provides = alpm_list_add(info->provides, linedup);  				}  			} -			/* TODO: we were going to move these things here, but it should wait. -			 * A better change would be to figure out how to restructure the DB. */ -				/* else if(!strcmp(line, "%REPLACES%")) { -				 * the REPLACES tag is special -- it only appears in sync repositories, -				 * not the local one. * -				while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { -					info->replaces = alpm_list_add(info->replaces, strdup(line)); -				} -			} else if(!strcmp(line, "%FORCE%")) { -				 * FORCE tag only appears in sync repositories, -				 * not the local one. * -				info->force = 1; -			} */  		}  		fclose(fp);  		fp = NULL; @@ -488,12 +486,13 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  	/* DELTAS */  	if(inforeq & INFRQ_DELTAS) { -		snprintf(path, PATH_MAX, "%s/%s-%s/deltas", db->path, info->name, info->version); +		snprintf(path, PATH_MAX, "%s/%s-%s/deltas", db->path, +				info->name, info->version);  		if((fp = fopen(path, "r"))) {  			while(!feof(fp)) {  				fgets(line, 255, fp);  				_alpm_strtrim(line); -				if(!strcmp(line, "%DELTAS%")) { +				if(strcmp(line, "%DELTAS%") == 0) {  					while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {  						info->deltas = alpm_list_add(info->deltas, _alpm_delta_parse(line));  					} @@ -561,7 +560,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  		}  		fprintf(fp, "%%NAME%%\n%s\n\n"  						"%%VERSION%%\n%s\n\n", info->name, info->version); -		if(info->desc[0]) { +		if(info->desc) {  			fprintf(fp, "%%DESC%%\n"  							"%s\n\n", info->desc);  		} @@ -573,7 +572,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  			fprintf(fp, "\n");  		}  		if(local) { -			if(info->url[0]) { +			if(info->url) {  				fprintf(fp, "%%URL%%\n"  								"%s\n\n", info->url);  			} @@ -584,7 +583,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  				}  				fprintf(fp, "\n");  			} -			if(info->arch[0]) { +			if(info->arch) {  				fprintf(fp, "%%ARCH%%\n"  								"%s\n\n", info->arch);  			} @@ -596,7 +595,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  				fprintf(fp, "%%INSTALLDATE%%\n"  								"%ju\n\n", (uintmax_t)info->installdate);  			} -			if(info->packager[0]) { +			if(info->packager) {  				fprintf(fp, "%%PACKAGER%%\n"  								"%s\n\n", info->packager);  			} @@ -695,18 +694,16 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)  			}  			fprintf(fp, "\n");  		} -		if(!local) { -			if(info->replaces) { -				fputs("%REPLACES%\n", fp); -				for(lp = info->replaces; lp; lp = lp->next) { -					fprintf(fp, "%s\n", (char *)lp->data); -				} -				fprintf(fp, "\n"); -			} -			if(info->force) { -				fprintf(fp, "%%FORCE%%\n" -								"\n"); +		if(info->replaces) { +			fputs("%REPLACES%\n", fp); +			for(lp = info->replaces; lp; lp = lp->next) { +				fprintf(fp, "%s\n", (char *)lp->data);  			} +			fprintf(fp, "\n"); +		} +		if(info->force) { +			/* note the extra newline character, which is necessary! */ +			fprintf(fp, "%%FORCE%%\n\n");  		}  		fclose(fp);  		fp = NULL; diff --git a/lib/libalpm/cache.c b/lib/libalpm/cache.c index 0ad923a5..bfc4fd9e 100644 --- a/lib/libalpm/cache.c +++ b/lib/libalpm/cache.c @@ -31,7 +31,6 @@  #include "log.h"  #include "alpm.h"  #include "util.h" -#include "error.h"  #include "package.h"  #include "group.h"  #include "db.h" @@ -81,10 +80,7 @@ void _alpm_db_free_pkgcache(pmdb_t *db)  	_alpm_log(PM_LOG_DEBUG, "freeing package cache for repository '%s'\n",  	                        db->treename); -	alpm_list_t *tmp; -	for(tmp = db->pkgcache; tmp; tmp = alpm_list_next(tmp)) { -		_alpm_pkg_free(tmp->data); -	} +	alpm_list_free_inner(db->pkgcache, (alpm_list_fn_free)_alpm_pkg_free);  	alpm_list_free(db->pkgcache);  	db->pkgcache = NULL; @@ -115,21 +111,15 @@ alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db)  int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg)  { -	pmpkg_t *newpkg; -  	ALPM_LOG_FUNC;  	if(db == NULL || pkg == NULL) {  		return(-1);  	} -	newpkg = _alpm_pkg_dup(pkg); -	if(newpkg == NULL) { -		return(-1); -	}  	_alpm_log(PM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n", -						alpm_pkg_get_name(newpkg), db->treename); -	db->pkgcache = alpm_list_add_sorted(db->pkgcache, newpkg, _alpm_pkg_cmp); +						alpm_pkg_get_name(pkg), db->treename); +	db->pkgcache = alpm_list_add_sorted(db->pkgcache, pkg, _alpm_pkg_cmp);  	_alpm_db_free_grpcache(db); @@ -208,33 +198,29 @@ int _alpm_db_load_grpcache(pmdb_t *db)  		pmpkg_t *pkg = lp->data;  		for(i = alpm_pkg_get_groups(pkg); i; i = i->next) { -			if(!alpm_list_find_str(db->grpcache, i->data)) { -				pmgrp_t *grp = _alpm_grp_new(); - -				strncpy(grp->name, i->data, GRP_NAME_LEN); -				grp->name[GRP_NAME_LEN-1] = '\0'; -				grp->packages = alpm_list_add_sorted(grp->packages, -																						 /* gross signature forces us to -																							* discard const */ -																						 (void*)alpm_pkg_get_name(pkg), -																						 _alpm_str_cmp); -				db->grpcache = alpm_list_add_sorted(db->grpcache, grp, _alpm_grp_cmp); -			} else { -				alpm_list_t *j; - -				for(j = db->grpcache; j; j = j->next) { -					pmgrp_t *grp = j->data; - -					if(strcmp(grp->name, i->data) == 0) { -						const char *pkgname = alpm_pkg_get_name(pkg); -						if(!alpm_list_find_str(grp->packages, pkgname)) { -							grp->packages = alpm_list_add_sorted(grp->packages, -							                                     (void*)pkgname, -																									 _alpm_str_cmp); -						} -					} +			const char *grpname = i->data; +			alpm_list_t *j; +			pmgrp_t *grp = NULL; +			int found = 0; + +			/* first look through the group cache for a group with this name */ +			for(j = db->grpcache; j; j = j->next) { +				grp = j->data; + +				if(strcmp(grp->name, grpname) == 0 +						&& !alpm_list_find_ptr(grp->packages, pkg)) { +					grp->packages = alpm_list_add(grp->packages, pkg); +					found = 1; +					break;  				}  			} +			if(found) { +				continue; +			} +			/* we didn't find the group, so create a new one with this name */ +			grp = _alpm_grp_new(grpname); +			grp->packages = alpm_list_add(grp->packages, pkg); +			db->grpcache = alpm_list_add(db->grpcache, grp);  		}  	} @@ -252,10 +238,6 @@ void _alpm_db_free_grpcache(pmdb_t *db)  	}  	for(lg = db->grpcache; lg; lg = lg->next) { -		pmgrp_t *grp = lg->data; - -		alpm_list_free(grp->packages); -		grp->packages = NULL;  		_alpm_grp_free(lg->data);  		lg->data = NULL;  	} diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 3442902c..68665e78 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -36,7 +36,6 @@  #include "handle.h"  #include "trans.h"  #include "util.h" -#include "error.h"  #include "log.h"  #include "cache.h"  #include "deps.h" @@ -49,12 +48,30 @@ pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2)  	MALLOC(conflict, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); -	strncpy(conflict->package1, package1, PKG_NAME_LEN); -	strncpy(conflict->package2, package2, PKG_NAME_LEN); +	STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL)); +	STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL));  	return(conflict);  } +void _alpm_conflict_free(pmconflict_t *conflict) +{ +	FREE(conflict->package2); +	FREE(conflict->package1); +	FREE(conflict); +} + +pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict) +{ +	pmconflict_t *newconflict; +	CALLOC(newconflict, 1, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + +	STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL)); +	STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL)); + +	return(newconflict); +} +  int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack)  {  	alpm_list_t *i; @@ -86,7 +103,7 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2)  {  	const char *pkg1name = alpm_pkg_get_name(pkg1);  	const char *pkg2name = alpm_pkg_get_name(pkg2); -	pmdepend_t *conf = alpm_splitdep(conflict); +	pmdepend_t *conf = _alpm_splitdep(conflict);  	int match = 0;  	match = alpm_depcmp(pkg2, conf); @@ -94,7 +111,7 @@ static int does_conflict(pmpkg_t *pkg1, const char *conflict, pmpkg_t *pkg2)  		_alpm_log(PM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n",  				pkg1name, pkg2name, conflict);  	} -	FREE(conf); +	_alpm_dep_free(conf);  	return(match);  } @@ -110,7 +127,7 @@ static void add_conflict(alpm_list_t **baddeps, const char *pkg1,  	if(conflict && !_alpm_conflict_isin(conflict, *baddeps)) {  		*baddeps = alpm_list_add(*baddeps, conflict);  	} else { -		FREE(conflict); +		_alpm_conflict_free(conflict);  	}  } @@ -200,9 +217,13 @@ alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages)  	return(baddeps);  } -/* Check for transaction conflicts */ -alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages) { -	return(alpm_list_join(_alpm_innerconflicts(packages), _alpm_outerconflicts(db, packages))); +/** Check the package conflicts in a database + * + * @param db_local the database to check + * @return an alpm_list_t of pmconflict_t + */ +alpm_list_t SYMEXPORT *alpm_checkdbconflicts(pmdb_t *db_local) { +	return(_alpm_innerconflicts(_alpm_db_get_pkgcache(db_local)));  }  /* Returns a alpm_list_t* of file conflicts. @@ -299,15 +320,15 @@ static alpm_list_t *add_fileconflict(alpm_list_t *conflicts,  										const char* name1, const char* name2)  {  	pmfileconflict_t *conflict; -	MALLOC(conflict, sizeof(pmfileconflict_t), return(conflicts)); +	MALLOC(conflict, sizeof(pmfileconflict_t), RET_ERR(PM_ERR_MEMORY, NULL));  	conflict->type = type; -	strncpy(conflict->target, name1, PKG_NAME_LEN); -	strncpy(conflict->file, filestr, CONFLICT_FILE_LEN); +	STRDUP(conflict->target, name1, RET_ERR(PM_ERR_MEMORY, NULL)); +	STRDUP(conflict->file, filestr, RET_ERR(PM_ERR_MEMORY, NULL));  	if(name2) { -		strncpy(conflict->ctarget, name2, PKG_NAME_LEN); +		STRDUP(conflict->ctarget, name2, RET_ERR(PM_ERR_MEMORY, NULL));  	} else { -		conflict->ctarget[0] = '\0'; +		conflict->ctarget = "";  	}  	conflicts = alpm_list_add(conflicts, conflict); @@ -317,6 +338,16 @@ static alpm_list_t *add_fileconflict(alpm_list_t *conflicts,  	return(conflicts);  } +void _alpm_fileconflict_free(pmfileconflict_t *conflict) +{ +	if(strlen(conflict->ctarget) > 0) { +		FREE(conflict->ctarget); +	} +	FREE(conflict->file);; +	FREE(conflict->target); +	FREE(conflict); +} +  /* Find file conflicts that may occur during the transaction with two checks:   * 1: check every target against every target   * 2: check every target against the filesystem */ @@ -351,13 +382,13 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *roo  		PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", (percent * 100),  		         numtargs, current);  		/* CHECK 1: check every target against every target */ +		_alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s\n", +								alpm_pkg_get_name(p1));  		for(j = i->next; j; j = j->next) {  			p2 = j->data;  			if(!p2) {  				continue;  			} -			_alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s and %s\n", -								alpm_pkg_get_name(p1), alpm_pkg_get_name(p2));  			tmpfiles = chk_fileconflicts(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2));  			if(tmpfiles) { diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index a846aace..71ed579d 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -23,27 +23,28 @@  #include "db.h"  #include "package.h" -#define CONFLICT_FILE_LEN 512 -  struct __pmconflict_t { -	char package1[PKG_NAME_LEN]; -	char package2[PKG_NAME_LEN]; +	char *package1; +	char *package2;  };  struct __pmfileconflict_t { -	char target[PKG_NAME_LEN]; +	char *target;  	pmfileconflicttype_t type; -	char file[CONFLICT_FILE_LEN]; -	char ctarget[PKG_NAME_LEN]; +	char *file; +	char *ctarget;  };  pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2); +pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict); +void _alpm_conflict_free(pmconflict_t *conflict);  int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack);  alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages);  alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages); -alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages);  alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *root); +void _alpm_fileconflict_free(pmfileconflict_t *conflict); +  #endif /* _ALPM_CONFLICT_H */  /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 1485c34a..e8ae11a3 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -39,8 +39,7 @@  #include "alpm_list.h"  #include "log.h"  #include "util.h" -#include "error.h" -#include "server.h" +#include "dload.h"  #include "handle.h"  #include "cache.h"  #include "alpm.h" @@ -190,14 +189,9 @@ int SYMEXPORT alpm_db_setserver(pmdb_t *db, const char *url)  	}  	if(url && strlen(url)) { -		pmserver_t *server; -		if((server = _alpm_server_new(url)) == NULL) { -			/* pm_errno is set by _alpm_server_new */ -			return(-1); -		} -		db->servers = alpm_list_add(db->servers, server); -		_alpm_log(PM_LOG_DEBUG, "adding new server to database '%s': protocol '%s', server '%s', path '%s'\n", -							db->treename, server->s_url->scheme, server->s_url->host, server->s_url->doc); +		db->servers = alpm_list_add(db->servers, strdup(url)); +		_alpm_log(PM_LOG_DEBUG, "adding new server URL to database '%s': %s\n", +				db->treename, url);  	} else {  		FREELIST(db->servers);  		_alpm_log(PM_LOG_DEBUG, "serverlist flushed for '%s'\n", db->treename); @@ -217,7 +211,6 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)  {  	alpm_list_t *lp;  	char path[PATH_MAX]; -	alpm_list_t *files = NULL;  	time_t newmtime = 0, lastupdate = 0;  	const char *dbpath;  	int ret; @@ -250,29 +243,21 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)  	/* build a one-element list */  	snprintf(path, PATH_MAX, "%s" DBEXT, db->treename); -	files = alpm_list_add(files, strdup(path)); -  	dbpath = alpm_option_get_dbpath(); -	ret = _alpm_downloadfiles_forreal(db->servers, dbpath, files, lastupdate, -			&newmtime, NULL, 0); -	FREELIST(files); +	ret = _alpm_download_single_file(path, db->servers, dbpath, +			lastupdate, &newmtime); +  	if(ret == 1) {  		/* mtimes match, do nothing */  		pm_errno = 0;  		return(1);  	} else if(ret == -1) { -		/* we use downloadLastErrString and downloadLastErrCode here, error returns from -		 * libdownload */ -		_alpm_log(PM_LOG_DEBUG, "failed to sync db: %s [%d]\n", -				downloadLastErrString, downloadLastErrCode); -		RET_ERR(PM_ERR_DB_SYNC, -1); +		/* pm_errno was set by the download code */ +		_alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast()); +		return(-1);  	} else { -		if(newmtime != 0) { -			_alpm_log(PM_LOG_DEBUG, "sync: new mtime for %s: %ju\n", -					db->treename, (uintmax_t)newmtime); -			_alpm_db_setlastupdate(db, newmtime); -		} +		/* form the path to the db location */  		snprintf(path, PATH_MAX, "%s%s" DBEXT, dbpath, db->treename);  		/* remove the old dir */ @@ -293,6 +278,12 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)  		if(_alpm_db_install(db, path) == -1) {  			return -1;  		} +		/* if we have a new mtime, set the DB last update value */ +		if(newmtime) { +			_alpm_log(PM_LOG_DEBUG, "sync: new mtime for %s: %ju\n", +					db->treename, (uintmax_t)newmtime); +			_alpm_db_setlastupdate(db, newmtime); +		}  	}  	return(0); @@ -319,8 +310,7 @@ const char SYMEXPORT *alpm_db_get_name(const pmdb_t *db)   */  const char SYMEXPORT *alpm_db_get_url(const pmdb_t *db)  { -	char path[PATH_MAX]; -	pmserver_t *s; +	char *url;  	ALPM_LOG_FUNC; @@ -328,10 +318,9 @@ const char SYMEXPORT *alpm_db_get_url(const pmdb_t *db)  	ASSERT(handle != NULL, return(NULL));  	ASSERT(db != NULL, return(NULL)); -	s = (pmserver_t*)db->servers->data; +	url = (char*)db->servers->data; -	snprintf(path, PATH_MAX, "%s://%s%s", s->s_url->scheme, s->s_url->host, s->s_url->doc); -	return strdup(path); +	return(url);  } @@ -445,26 +434,21 @@ pmdb_t *_alpm_db_new(const char *dbpath, const char *treename)  	CALLOC(db->path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));  	sprintf(db->path, "%s%s/", dbpath, treename); - -	strncpy(db->treename, treename, PATH_MAX); +	STRDUP(db->treename, treename, RET_ERR(PM_ERR_MEMORY, NULL));  	return(db);  }  void _alpm_db_free(pmdb_t *db)  { -	alpm_list_t *tmp; -  	ALPM_LOG_FUNC;  	/* cleanup pkgcache */  	_alpm_db_free_pkgcache(db);  	/* cleanup server list */ -	for(tmp = db->servers; tmp; tmp = alpm_list_next(tmp)) { -		_alpm_server_free(tmp->data); -	} -	alpm_list_free(db->servers); +	FREELIST(db->servers);  	FREE(db->path); +	FREE(db->treename);  	FREE(db);  	return; @@ -500,18 +484,16 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles)  		for(j = _alpm_db_get_pkgcache(db); j; j = j->next) {  			pmpkg_t *pkg = j->data;  			const char *matched = NULL; +			const char *name = alpm_pkg_get_name(pkg); +			const char *desc = alpm_pkg_get_desc(pkg); -			/* check name */ -			if (regexec(®, alpm_pkg_get_name(pkg), 0, 0, 0) == 0) { -				matched = alpm_pkg_get_name(pkg); -			} -			/* check plain text name */ -			else if (strstr(alpm_pkg_get_name(pkg), targ)) { -				matched = alpm_pkg_get_name(pkg); +			/* check name as regex AND as plain text */ +			if(name && (regexec(®, name, 0, 0, 0) == 0 || strstr(name, targ))) { +				matched = name;  			}  			/* check desc */ -			else if (regexec(®, alpm_pkg_get_desc(pkg), 0, 0, 0) == 0) { -				matched = alpm_pkg_get_desc(pkg); +			else if (desc && regexec(®, desc, 0, 0, 0) == 0) { +				matched = desc;  			}  			/* check provides */  			/* TODO: should we be doing this, and should we print something diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 8c8c9bd7..743fa788 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -40,7 +40,7 @@ typedef enum _pmdbinfrq_t {  /* Database */  struct __pmdb_t {  	char *path; -	char treename[PATH_MAX]; +	char *treename;  	void *handle;  	alpm_list_t *pkgcache;  	alpm_list_t *grpcache; diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 3d33c595..fdb4d99b 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -1,7 +1,7 @@  /*   *  delta.c   * - *  Copyright (c) 2007 by Judd Vinet <jvinet@zeroflux.org> + *  Copyright (c) 2007-2008 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -21,14 +21,14 @@  #include <stdlib.h>  #include <string.h> +#include <limits.h>  /* libalpm */  #include "delta.h" -#include "error.h" +#include "alpm_list.h"  #include "util.h"  #include "log.h" -#include "alpm_list.h" -#include "alpm.h" +#include "graph.h"  /** \addtogroup alpm_deltas Delta Functions   * @brief Functions to manipulate libalpm deltas @@ -37,200 +37,222 @@  const char SYMEXPORT *alpm_delta_get_from(pmdelta_t *delta)  { -	ALPM_LOG_FUNC; - -	/* Sanity checks */  	ASSERT(delta != NULL, return(NULL)); -  	return(delta->from);  } -const char SYMEXPORT *alpm_delta_get_to(pmdelta_t *delta) +const char SYMEXPORT *alpm_delta_get_from_md5sum(pmdelta_t *delta)  { -	ALPM_LOG_FUNC; - -	/* Sanity checks */  	ASSERT(delta != NULL, return(NULL)); +	return(delta->from_md5); +} +const char SYMEXPORT *alpm_delta_get_to(pmdelta_t *delta) +{ +	ASSERT(delta != NULL, return(NULL));  	return(delta->to);  } -unsigned long SYMEXPORT alpm_delta_get_size(pmdelta_t *delta) +const char SYMEXPORT *alpm_delta_get_to_md5sum(pmdelta_t *delta)  { -	ALPM_LOG_FUNC; - -	/* Sanity checks */ -	ASSERT(delta != NULL, return(-1)); - -	return(delta->size); +	ASSERT(delta != NULL, return(NULL)); +	return(delta->to_md5);  }  const char SYMEXPORT *alpm_delta_get_filename(pmdelta_t *delta)  { -	ALPM_LOG_FUNC; - -	/* Sanity checks */  	ASSERT(delta != NULL, return(NULL)); - -	return(delta->filename); +	return(delta->delta);  }  const char SYMEXPORT *alpm_delta_get_md5sum(pmdelta_t *delta)  { -	ALPM_LOG_FUNC; - -	/* Sanity checks */  	ASSERT(delta != NULL, return(NULL)); +	return(delta->delta_md5); +} -	return(delta->md5sum); +unsigned long SYMEXPORT alpm_delta_get_size(pmdelta_t *delta) +{ +	ASSERT(delta != NULL, return(-1)); +	return(delta->delta_size);  }  /** @} */ -/** Calculates the combined size of a list of delta files. - * - * @param deltas the list of pmdelta_t * objects - * - * @return the combined size - */ -unsigned long _alpm_delta_path_size(alpm_list_t *deltas) +static alpm_list_t *delta_graph_init(alpm_list_t *deltas)  { -	unsigned long sum = 0; -	alpm_list_t *dlts = deltas; - -	while(dlts) { -		pmdelta_t *d = (pmdelta_t *)alpm_list_getdata(dlts); -		sum += d->size; +	alpm_list_t *i, *j; +	alpm_list_t *vertices = NULL; +	/* create the vertices */ +	for(i = deltas; i; i = i->next) { +		char *fpath, *md5sum; +		pmgraph_t *v = _alpm_graph_new(); +		pmdelta_t *vdelta = i->data; +		vdelta->download_size = vdelta->delta_size; +		v->weight = ULONG_MAX; + +		/* determine whether the delta file already exists */ +		fpath = _alpm_filecache_find(vdelta->delta); +		md5sum = alpm_get_md5sum(fpath); +		if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { +			vdelta->download_size = 0; +		} +		FREE(fpath); +		FREE(md5sum); + +		/* determine whether a base 'from' file exists */ +		fpath = _alpm_filecache_find(vdelta->from); +		md5sum = alpm_get_md5sum(fpath); +		if(fpath && md5sum && strcmp(md5sum, vdelta->from_md5) == 0) { +			v->weight = vdelta->download_size; +		} +		FREE(fpath); +		FREE(md5sum); -		dlts = alpm_list_next(dlts); +		v->data = vdelta; +		vertices = alpm_list_add(vertices, v);  	} -	return(sum); +	/* compute the edges */ +	for(i = vertices; i; i = i->next) { +		pmgraph_t *v_i = i->data; +		pmdelta_t *d_i = v_i->data; +		/* loop a second time so we make all possible comparisons */ +		for(j = vertices; j; j = j->next) { +			pmgraph_t *v_j = j->data; +			pmdelta_t *d_j = v_j->data; +			/* We want to create a delta tree like the following: +			 *          1_to_2 +			 *            | +			 * 1_to_3   2_to_3 +			 *   \        / +			 *     3_to_4 +			 * If J 'from' is equal to I 'to', then J is a child of I. +			 * */ +			if(strcmp(d_j->from, d_i->to) == 0 +					&& strcmp(d_j->from_md5, d_i->to_md5) == 0) { +				v_i->children = alpm_list_add(v_i->children, v_j); +			} +		} +		v_i->childptr = v_i->children; +	} +	return(vertices);  } -/** Calculates the combined size of a list of delta files that are not - * in the cache. - * - * @param deltas the list of pmdelta_t * objects - * - * @return the combined size - */ -unsigned long _alpm_delta_path_size_uncached(alpm_list_t *deltas) -{ -	unsigned long sum = 0; -	alpm_list_t *dlts = deltas; - -	while(dlts) { -		pmdelta_t *d = (pmdelta_t *)alpm_list_getdata(dlts); -		char *fname = _alpm_filecache_find(d->filename); +static unsigned long delta_vert(alpm_list_t *vertices, +		const char *to, const char *to_md5, alpm_list_t **path) { +	alpm_list_t *i; +	pmgraph_t *v; +	while(1) { +		v = NULL; +		/* find the smallest vertice not visited yet */ +		for(i = vertices; i; i = i->next) { +			pmgraph_t *v_i = i->data; + +			if(v_i->state == -1) { +				continue; +			} -		if(!fname) { -			sum += d->size; +			if(v == NULL || v_i->weight < v->weight) { +				v = v_i; +			} +		} +		if(v == NULL || v->weight == ULONG_MAX) { +			break;  		} -		FREE(fname); +		v->state = -1; -		dlts = alpm_list_next(dlts); -	} +		v->childptr = v->children; +		while(v->childptr) { +			pmgraph_t *v_c = v->childptr->data; +			pmdelta_t *d_c = v_c->data; +			if(v_c->weight > v->weight + d_c->download_size) { +				v_c->weight = v->weight + d_c->download_size; +				v_c->parent = v; +			} -	return(sum); -} +			v->childptr = (v->childptr)->next; -/** Calculates the shortest path from one version to another. - * - * The shortest path is defined as the path with the smallest combined - * size, not the length of the path. - * - * The algorithm is based on Dijkstra's shortest path algorithm. - * - * @param deltas the list of pmdelta_t * objects that a package has - * @param from the version to start from - * @param to the version to end at - * @param path the current path - * - * @return the list of pmdelta_t * objects that has the smallest size. - * NULL (the empty list) is returned if there is no path between the - * versions. - */ -static alpm_list_t *shortest_delta_path(alpm_list_t *deltas, -		const char *from, const char *to, alpm_list_t *path) -{ -	alpm_list_t *d; -	alpm_list_t *shortest = NULL; - -	/* Found the 'to' version, this is a good path so return it. */ -	if(strcmp(from, to) == 0) { -		return(path); +		}  	} -	for(d = deltas; d; d = alpm_list_next(d)) { -		pmdelta_t *v = alpm_list_getdata(d); +	v = NULL; +	unsigned long bestsize = 0; -		/* If this vertex has already been visited in the path, go to the -		 * next vertex. */ -		if(alpm_list_find_ptr(path, v)) { -			continue; -		} +	for(i = vertices; i; i = i->next) { +		pmgraph_t *v_i = i->data; +		pmdelta_t *d_i = v_i->data; -		/* Once we find a vertex that starts at the 'from' version, -		 * recursively find the shortest path using the 'to' version of this -		 * current vertex as the 'from' version in the function call. */ -		if(strcmp(v->from, from) == 0) { -			alpm_list_t *newpath = alpm_list_copy(path); -			newpath = alpm_list_add(newpath, v); -			newpath = shortest_delta_path(deltas, v->to, to, newpath); - -			if(newpath != NULL) { -				/* The path returned works, now use it unless there is already a -				 * shorter path found. */ -				if(shortest == NULL) { -					shortest = newpath; -				} else if(_alpm_delta_path_size(shortest) > _alpm_delta_path_size(newpath)) { -					alpm_list_free(shortest); -					shortest = newpath; -				} else { -					alpm_list_free(newpath); -				} +		if(strcmp(d_i->to, to) == 0 +				|| strcmp(d_i->to_md5, to_md5) == 0) { +			if(v == NULL || v_i->weight < v->weight) { +				v = v_i; +				bestsize = v->weight;  			}  		}  	} -	alpm_list_free(path); +	alpm_list_t *rpath = NULL; +	while(v != NULL) { +		pmdelta_t *vdelta = v->data; +		rpath = alpm_list_add(rpath, vdelta); +		v = v->parent; +	} +	*path = alpm_list_reverse(rpath); +	alpm_list_free(rpath); -	return(shortest); +	return(bestsize);  }  /** Calculates the shortest path from one version to another. - *   * The shortest path is defined as the path with the smallest combined   * size, not the length of the path. - * - * @param deltas the list of pmdelta_t * objects that a package has - * @param from the version to start from - * @param to the version to end at - * - * @return the list of pmdelta_t * objects that has the smallest size. - * NULL (the empty list) is returned if there is no path between the - * versions. + * @param deltas the list of pmdelta_t * objects that a file has + * @param to the file to start the search at + * @param to_md5 the md5sum of the above named file + * @param path the pointer to a list location where pmdelta_t * objects that + * have the smallest size are placed. NULL is set if there is no path + * possible with the files available. + * @return the size of the path stored, or ULONG_MAX if path is unfindable   */ -alpm_list_t *_alpm_shortest_delta_path(alpm_list_t *deltas, const char *from, -		const char *to) +unsigned long _alpm_shortest_delta_path(alpm_list_t *deltas, +		const char *to, const char *to_md5, alpm_list_t **path)  { -	alpm_list_t *path = NULL; +	alpm_list_t *bestpath = NULL; +	alpm_list_t *vertices; +	unsigned long bestsize = ULONG_MAX; + +	ALPM_LOG_FUNC; + +	if(deltas == NULL) { +		*path = NULL; +		return(bestsize); +	} + +	_alpm_log(PM_LOG_DEBUG, "started delta shortest-path search\n"); + +	vertices = delta_graph_init(deltas); + +	bestsize = delta_vert(vertices, to, to_md5, &bestpath); -	path = shortest_delta_path(deltas, from, to, path); +	_alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete\n"); -	return(path); +	alpm_list_free_inner(vertices, _alpm_graph_free); +	alpm_list_free(vertices); + +	*path = bestpath; +	return(bestsize);  }  /** Parses the string representation of a pmdelta_t object. - *   * This function assumes that the string is in the correct format. - * + * This format is as follows: + * $oldfile $oldmd5 $newfile $newmd5 $deltafile $deltamd5 $deltasize   * @param line the string to parse - *   * @return A pointer to the new pmdelta_t object   */ +/* TODO this does not really belong here, but in a parsing lib */  pmdelta_t *_alpm_delta_parse(char *line)  {  	pmdelta_t *delta; @@ -241,26 +263,47 @@ pmdelta_t *_alpm_delta_parse(char *line)  	tmp2 = tmp;  	tmp = strchr(tmp, ' ');  	*(tmp++) = '\0'; -	strncpy(delta->from, tmp2, DLT_VERSION_LEN); +	STRDUP(delta->from, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));  	tmp2 = tmp;  	tmp = strchr(tmp, ' ');  	*(tmp++) = '\0'; -	strncpy(delta->to, tmp2, DLT_VERSION_LEN); +	STRDUP(delta->from_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));  	tmp2 = tmp;  	tmp = strchr(tmp, ' ');  	*(tmp++) = '\0'; -	delta->size = atol(tmp2); +	STRDUP(delta->to, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));  	tmp2 = tmp;  	tmp = strchr(tmp, ' ');  	*(tmp++) = '\0'; -	strncpy(delta->filename, tmp2, DLT_FILENAME_LEN); +	STRDUP(delta->to_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); -	strncpy(delta->md5sum, tmp, DLT_MD5SUM_LEN); +	tmp2 = tmp; +	tmp = strchr(tmp, ' '); +	*(tmp++) = '\0'; +	STRDUP(delta->delta, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + +	tmp2 = tmp; +	tmp = strchr(tmp, ' '); +	*(tmp++) = '\0'; +	STRDUP(delta->delta_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + +	delta->delta_size = atol(tmp);  	return(delta);  } +void _alpm_delta_free(pmdelta_t *delta) +{ +	FREE(delta->from); +	FREE(delta->from_md5); +	FREE(delta->to); +	FREE(delta->to_md5); +	FREE(delta->delta); +	FREE(delta->delta_md5); +	FREE(delta); +} +  /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h index 3065d4d1..33d47e1e 100644 --- a/lib/libalpm/delta.h +++ b/lib/libalpm/delta.h @@ -1,7 +1,7 @@  /*   *  delta.h   * - *  Copyright (c) 2007 by Judd Vinet <jvinet@zeroflux.org> + *  Copyright (c) 2007-2008 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -21,22 +21,29 @@  #include "alpm.h" -#define DLT_FILENAME_LEN 512 -#define DLT_VERSION_LEN  64 -#define DLT_MD5SUM_LEN   33 -  struct __pmdelta_t { -	char from[DLT_VERSION_LEN]; -	char to[DLT_VERSION_LEN]; -	unsigned long size; -	char filename[DLT_FILENAME_LEN]; -	char md5sum[DLT_MD5SUM_LEN]; +	/** filename of the 'before' file */ +	char *from; +	/** md5sum of the 'before' file */ +	char *from_md5; +	/** filename of the 'after' file */ +	char *to; +	/** md5sum of the 'after' file */ +	char *to_md5; +	/** filename of the delta patch */ +	char *delta; +	/** md5sum of the delta file */ +	char *delta_md5; +	/** filesize of the delta file */ +	unsigned long delta_size; +	/** download filesize of the delta file */ +	unsigned long download_size;  }; -unsigned long _alpm_delta_path_size(alpm_list_t *deltas); -unsigned long _alpm_delta_path_size_uncached(alpm_list_t *deltas);  pmdelta_t *_alpm_delta_parse(char *line); -alpm_list_t *_alpm_shortest_delta_path(alpm_list_t *deltas, const char *from, const char *to); +void _alpm_delta_free(pmdelta_t *delta); +unsigned long _alpm_shortest_delta_path(alpm_list_t *deltas, +		const char *to, const char *to_md5, alpm_list_t **path);  #endif /* _ALPM_DELTA_H */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index b967243d..b171ccc7 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -30,37 +30,21 @@  #include "alpm_list.h"  #include "util.h"  #include "log.h" -#include "error.h" +#include "graph.h"  #include "package.h"  #include "db.h"  #include "cache.h"  #include "handle.h" -static pmgraph_t *_alpm_graph_new(void) +void _alpm_dep_free(pmdepend_t *dep)  { -	pmgraph_t *graph = NULL; - -	MALLOC(graph, sizeof(pmgraph_t), RET_ERR(PM_ERR_MEMORY, NULL)); - -	if(graph) { -		graph->state = 0; -		graph->data = NULL; -		graph->parent = NULL; -		graph->children = NULL; -		graph->childptr = NULL; -	} -	return(graph); +	FREE(dep->name); +	FREE(dep->version); +	FREE(dep);  } -static void _alpm_graph_free(void *data) -{ -	pmgraph_t *graph = data; -	alpm_list_free(graph->children); -	free(graph); -} - -pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepmod_t depmod, -		const char *depname, const char *depversion) +pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepend_t *dep, +		const char *causingpkg)  {  	pmdepmissing_t *miss; @@ -68,24 +52,27 @@ pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepmod_t depmod,  	MALLOC(miss, sizeof(pmdepmissing_t), RET_ERR(PM_ERR_MEMORY, NULL)); -	strncpy(miss->target, target, PKG_NAME_LEN); -	miss->depend.mod = depmod; -	strncpy(miss->depend.name, depname, PKG_NAME_LEN); -	if(depversion) { -		strncpy(miss->depend.version, depversion, PKG_VERSION_LEN); -	} else { -		miss->depend.version[0] = 0; -	} +	STRDUP(miss->target, target, RET_ERR(PM_ERR_MEMORY, NULL)); +	miss->depend = _alpm_dep_dup(dep); +	STRDUP(miss->causingpkg, causingpkg, RET_ERR(PM_ERR_MEMORY, NULL));  	return(miss);  } +void _alpm_depmiss_free(pmdepmissing_t *miss) +{ +	_alpm_dep_free(miss->depend); +	FREE(miss->target); +	FREE(miss->causingpkg); +	FREE(miss); +} +  /* Convert a list of pmpkg_t * to a graph structure,   * with a edge for each dependency.   * Returns a list of vertices (one vertex = one package)   * (used by alpm_sortbydeps)   */ -static alpm_list_t *_alpm_graph_init(alpm_list_t *targets) +static alpm_list_t *dep_graph_init(alpm_list_t *targets)  {  	alpm_list_t *i, *j, *k;  	alpm_list_t *vertices = NULL; @@ -121,20 +108,19 @@ static alpm_list_t *_alpm_graph_init(alpm_list_t *targets)  /* Re-order a list of target packages with respect to their dependencies.   * - * Example (PM_TRANS_TYPE_ADD): + * Example (reverse == 0):   *   A depends on C   *   B depends on A   *   Target order is A,B,C,D   *   *   Should be re-ordered to C,A,B,D   * - * mode should be either PM_TRANS_TYPE_ADD or PM_TRANS_TYPE_REMOVE.  This - * affects the dependency order sortbydeps() will use. + * if reverse is > 0, the dependency order will be reversed.   *   * This function returns the new alpm_list_t* target list.   *   */ -alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode) +alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse)  {  	alpm_list_t *newtargs = NULL;  	alpm_list_t *vertices = NULL; @@ -149,7 +135,7 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode)  	_alpm_log(PM_LOG_DEBUG, "started sorting dependencies\n"); -	vertices = _alpm_graph_init(targets); +	vertices = dep_graph_init(targets);  	vptr = vertices;  	vertex = vertices->data; @@ -169,7 +155,7 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode)  				pmpkg_t *vertexpkg = vertex->data;  				pmpkg_t *childpkg = nextchild->data;  				_alpm_log(PM_LOG_WARNING, _("dependency cycle detected:\n")); -				if(mode == PM_TRANS_TYPE_REMOVE) { +				if(reverse) {  					_alpm_log(PM_LOG_WARNING, _("%s will be removed after its %s dependency\n"), vertexpkg->name, childpkg->name);  				} else {  					_alpm_log(PM_LOG_WARNING, _("%s will be installed before its %s dependency\n"), vertexpkg->name, childpkg->name); @@ -194,8 +180,8 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode)  	_alpm_log(PM_LOG_DEBUG, "sorting dependencies finished\n"); -	if(mode == PM_TRANS_TYPE_REMOVE) { -		/* we're removing packages, so reverse the order */ +	if(reverse) { +		/* reverse the order */  		alpm_list_t *tmptargs = alpm_list_reverse(newtargs);  		/* free the old one */  		alpm_list_free(newtargs); @@ -217,6 +203,31 @@ static int satisfycmp(const void *pkg, const void *depend)  /** Checks dependencies and returns missing ones in a list.   * Dependencies can include versions with depmod operators.   * @param db pointer to the local package database + * @param targets an alpm_list_t* of dependencies strings to satisfy + * @return an alpm_list_t* of missing dependencies strings + */ +alpm_list_t SYMEXPORT *alpm_deptest(pmdb_t *db, alpm_list_t *targets) +{ +	alpm_list_t *i, *ret = NULL; + +	for(i = targets; i; i = alpm_list_next(i)) { +		pmdepend_t *dep; +		char *target; + +		target = alpm_list_getdata(i); +		dep = _alpm_splitdep(target); + +		if(!alpm_list_find(_alpm_db_get_pkgcache(db), dep, satisfycmp)) { +			ret = alpm_list_add(ret, target); +		} +		_alpm_dep_free(dep); +	} +	return(ret); +} + +/** Checks dependencies and returns missing ones in a list. + * Dependencies can include versions with depmod operators. + * @param db pointer to the local package database   * @param reversedeps handles the backward dependencies   * @param remove an alpm_list_t* of packages to be removed   * @param upgrade an alpm_list_t* of packages to be upgraded (remove-then-upgrade) @@ -264,8 +275,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps,  				_alpm_log(PM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n",  						missdepstring, alpm_pkg_get_name(tp));  				free(missdepstring); -				miss = _alpm_depmiss_new(alpm_pkg_get_name(tp), depend->mod, -						depend->name, depend->version); +				miss = _alpm_depmiss_new(alpm_pkg_get_name(tp), depend, "");  				baddeps = alpm_list_add(baddeps, miss);  			}  		} @@ -278,18 +288,18 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps,  			pmpkg_t *lp = i->data;  			for(j = alpm_pkg_get_depends(lp); j; j = j->next) {  				pmdepend_t *depend = j->data; +				pmpkg_t *causingpkg = alpm_list_find(modified, depend, satisfycmp);  				/* we won't break this depend, if it is already broken, we ignore it */  				/* 1. check upgrade list for satisfiers */  				/* 2. check dblist for satisfiers */ -				if(alpm_list_find(modified, depend, satisfycmp) && +				if(causingpkg &&  				   !alpm_list_find(upgrade, depend, satisfycmp) &&  				   !alpm_list_find(dblist, depend, satisfycmp)) {  					char *missdepstring = alpm_dep_get_string(depend);  					_alpm_log(PM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n",  							missdepstring, alpm_pkg_get_name(lp));  					free(missdepstring); -					miss = _alpm_depmiss_new(lp->name, depend->mod, -							depend->name, depend->version); +					miss = _alpm_depmiss_new(lp->name, depend, alpm_pkg_get_name(causingpkg));  					baddeps = alpm_list_add(baddeps, miss);  				}  			} @@ -356,7 +366,7 @@ int SYMEXPORT alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep)  	return(satisfy);  } -pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring) +pmdepend_t *_alpm_splitdep(const char *depstring)  {  	pmdepend_t *depend;  	char *ptr = NULL; @@ -365,9 +375,9 @@ pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring)  	if(depstring == NULL) {  		return(NULL);  	} -	newstr = strdup(depstring); +	STRDUP(newstr, depstring, RET_ERR(PM_ERR_MEMORY, NULL)); -	MALLOC(depend, sizeof(pmdepend_t), return(NULL)); +	CALLOC(depend, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL));  	/* Find a version comparator if one exists. If it does, set the type and  	 * increment the ptr accordingly so we can copy the right strings. */ @@ -391,25 +401,36 @@ pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring)  		depend->mod = PM_DEP_MOD_GT;  		*ptr = '\0';  		ptr += 1; -  	} else { -		/* no version specified - copy in the name and return it */ +		/* no version specified - copy the name and return it */  		depend->mod = PM_DEP_MOD_ANY; -		strncpy(depend->name, newstr, PKG_NAME_LEN); -		depend->version[0] = '\0'; +		STRDUP(depend->name, newstr, RET_ERR(PM_ERR_MEMORY, NULL)); +		depend->version = NULL;  		free(newstr);  		return(depend);  	}  	/* if we get here, we have a version comparator, copy the right parts  	 * to the right places */ -	strncpy(depend->name, newstr, PKG_NAME_LEN); -	strncpy(depend->version, ptr, PKG_VERSION_LEN); +	STRDUP(depend->name, newstr, RET_ERR(PM_ERR_MEMORY, NULL)); +	STRDUP(depend->version, ptr, RET_ERR(PM_ERR_MEMORY, NULL));  	free(newstr);  	return(depend);  } +pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep) +{ +	pmdepend_t *newdep; +	CALLOC(newdep, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL)); + +	STRDUP(newdep->name, dep->name, RET_ERR(PM_ERR_MEMORY, NULL)); +	STRDUP(newdep->version, dep->version, RET_ERR(PM_ERR_MEMORY, NULL)); +	newdep->mod = dep->mod; + +	return(newdep); +} +  /* These parameters are messy. We check if this package, given a list of   * targets and a db is safe to remove. We do NOT remove it if it is in the   * target list, or if if the package was explictly installed and @@ -417,7 +438,7 @@ pmdepend_t SYMEXPORT *alpm_splitdep(const char *depstring)  static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets,  		int include_explicit)  { -	alpm_list_t *i, *requiredby; +	alpm_list_t *i, *j;  	if(_alpm_pkg_find(alpm_pkg_get_name(pkg), targets)) {  		return(0); @@ -439,15 +460,17 @@ static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets,  	 * if checkdeps detected it would break something */  	/* see if other packages need it */ -	requiredby = alpm_pkg_compute_requiredby(pkg); -	for(i = requiredby; i; i = i->next) { -		pmpkg_t *reqpkg = _alpm_db_get_pkgfromcache(db, i->data); -		if(reqpkg && !_alpm_pkg_find(alpm_pkg_get_name(reqpkg), targets)) { -			FREELIST(requiredby); -			return(0); +	for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { +		pmpkg_t *lpkg = i->data; +		for(j = alpm_pkg_get_depends(lpkg); j; j = j->next) { +			if(alpm_depcmp(pkg, j->data)) { +				if(!_alpm_pkg_find(lpkg->name, targets)) { +					return(0); +				} +				break; +			}  		}  	} -	FREELIST(requiredby);  	/* it's ok to remove */  	return(1); @@ -523,7 +546,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,  	for(i = deps; i; i = i->next) {  		int found = 0;  		pmdepmissing_t *miss = i->data; -		pmdepend_t *missdep = &(miss->depend); +		pmdepend_t *missdep = alpm_miss_get_dep(miss);  		pmpkg_t *sync = NULL;  		/* check if one of the packages in *list already satisfies this dependency */ @@ -548,7 +571,8 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,  			if(!sync) {  				continue;  			} -			found = alpm_depcmp(sync, missdep) && !_alpm_pkg_find(alpm_pkg_get_name(sync), remove); +			found = alpm_depcmp(sync, missdep) && !_alpm_pkg_find(alpm_pkg_get_name(sync), remove) +				&& !_alpm_pkg_find(alpm_pkg_get_name(sync), *list);  			if(!found) {  				continue;  			} @@ -570,7 +594,8 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,  					continue;  				}  				found = alpm_depcmp(sync, missdep) && strcmp(sync->name, missdep->name) -					&& !_alpm_pkg_find(alpm_pkg_get_name(sync), remove); +					&& !_alpm_pkg_find(alpm_pkg_get_name(sync), remove) +					&& !_alpm_pkg_find(alpm_pkg_get_name(sync), *list);  				if(!found) {  					continue;  				} @@ -611,7 +636,8 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,  	_alpm_log(PM_LOG_DEBUG, "finished resolving dependencies\n"); -	FREELIST(deps); +	alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); +	alpm_list_free(deps);  	return(0); @@ -627,7 +653,17 @@ const char SYMEXPORT *alpm_miss_get_target(const pmdepmissing_t *miss)  	/* Sanity checks */  	ASSERT(miss != NULL, return(NULL)); -	return miss->target; +	return(miss->target); +} + +const char SYMEXPORT *alpm_miss_get_causingpkg(const pmdepmissing_t *miss) +{ +	ALPM_LOG_FUNC; + +	/* Sanity checks */ +	ASSERT(miss != NULL, return(NULL)); + +	return miss->causingpkg;  }  pmdepend_t SYMEXPORT *alpm_miss_get_dep(pmdepmissing_t *miss) @@ -637,7 +673,7 @@ pmdepend_t SYMEXPORT *alpm_miss_get_dep(pmdepmissing_t *miss)  	/* Sanity checks */  	ASSERT(miss != NULL, return(NULL)); -	return &(miss->depend); +	return(miss->depend);  }  pmdepmod_t SYMEXPORT alpm_dep_get_mod(const pmdepend_t *dep) @@ -647,7 +683,7 @@ pmdepmod_t SYMEXPORT alpm_dep_get_mod(const pmdepend_t *dep)  	/* Sanity checks */  	ASSERT(dep != NULL, return(-1)); -	return dep->mod; +	return(dep->mod);  }  const char SYMEXPORT *alpm_dep_get_name(const pmdepend_t *dep) @@ -657,7 +693,7 @@ const char SYMEXPORT *alpm_dep_get_name(const pmdepend_t *dep)  	/* Sanity checks */  	ASSERT(dep != NULL, return(NULL)); -	return dep->name; +	return(dep->name);  }  const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep) @@ -667,7 +703,7 @@ const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep)  	/* Sanity checks */  	ASSERT(dep != NULL, return(NULL)); -	return dep->version; +	return(dep->version);  }  /** Reverse of splitdep; make a dep string from a pmdepend_t struct. @@ -677,7 +713,7 @@ const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep)   */  char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep)  { -	char *opr, *str = NULL; +	char *name, *opr, *ver, *str = NULL;  	size_t len;  	ALPM_LOG_FUNC; @@ -685,6 +721,12 @@ char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep)  	/* Sanity checks */  	ASSERT(dep != NULL, return(NULL)); +	if(dep->name) { +		name = dep->name; +	} else { +		name = ""; +	} +  	switch(dep->mod) {  		case PM_DEP_MOD_ANY:  			opr = ""; @@ -709,11 +751,18 @@ char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep)  			break;  	} +	if(dep->version) { +		ver = dep->version; +	} else { +		ver = ""; +	} +  	/* we can always compute len and print the string like this because opr -	 * and ver will be empty when PM_DEP_MOD_ANY is the depend type */ -	len = strlen(dep->name) + strlen(opr) + strlen(dep->version) + 1; +	 * and ver will be empty when PM_DEP_MOD_ANY is the depend type. the +	 * reassignments above also ensure we do not do a strlen(NULL). */ +	len = strlen(name) + strlen(opr) + strlen(ver) + 1;  	MALLOC(str, len, RET_ERR(PM_ERR_MEMORY, NULL)); -	snprintf(str, len, "%s%s%s", dep->name, opr, dep->version); +	snprintf(str, len, "%s%s%s", name, opr, ver);  	return(str);  } diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index 75cbb5bc..fe851288 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -29,31 +29,28 @@  /* Dependency */  struct __pmdepend_t {  	pmdepmod_t mod; -	char name[PKG_NAME_LEN]; -	char version[PKG_VERSION_LEN]; +	char *name; +	char *version;  };  /* Missing dependency */  struct __pmdepmissing_t { -	char target[PKG_NAME_LEN]; -	pmdepend_t depend; +	char *target; +	pmdepend_t *depend; +	char *causingpkg; /* this is used in case of remove dependency error only */  }; -/* Graphs */ -struct __pmgraph_t { -	int state; /* 0: untouched, -1: entered, other: leaving time */ -	void *data; -	struct __pmgraph_t *parent; /* where did we come from? */ -	alpm_list_t *children; -	alpm_list_t *childptr; /* points to a child in children list */ -}; - -pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepmod_t depmod, -		const char *depname, const char *depversion); -alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode); +void _alpm_dep_free(pmdepend_t *dep); +pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep); +pmdepmissing_t *_alpm_depmiss_new(const char *target, pmdepend_t *dep, +		const char *causinpkg); +void _alpm_depmiss_free(pmdepmissing_t *miss); +alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse);  void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit);  int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg, -                      alpm_list_t **list, alpm_list_t *remove, pmtrans_t *trans, alpm_list_t **data); +		alpm_list_t **list, alpm_list_t *remove, pmtrans_t *trans, alpm_list_t +		**data); +pmdepend_t *_alpm_splitdep(const char *depstring);  #endif /* _ALPM_DEPS_H */ diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c new file mode 100644 index 00000000..44acec70 --- /dev/null +++ b/lib/libalpm/dload.c @@ -0,0 +1,463 @@ +/* + *  download.c + * + *  Copyright (c) 2002-2008 by Judd Vinet <jvinet@zeroflux.org> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +/* the following two are needed on BSD for libfetch */ +#if defined(HAVE_SYS_SYSLIMITS_H) +#include <sys/syslimits.h> /* PATH_MAX */ +#endif +#if defined(HAVE_SYS_PARAM_H) +#include <sys/param.h> /* MAXHOSTNAMELEN */ +#endif + +#if defined(HAVE_LIBDOWNLOAD) +#include <download.h> +#elif defined(HAVE_LIBFETCH) +#include <fetch.h> +#define downloadFreeURL fetchFreeURL +#define downloadLastErrCode fetchLastErrCode +#define downloadLastErrString fetchLastErrString +#define downloadParseURL fetchParseURL +#define downloadTimeout fetchTimeout +#define downloadXGet fetchXGet +#endif + +/* libalpm */ +#include "dload.h" +#include "alpm_list.h" +#include "alpm.h" +#include "log.h" +#include "util.h" +#include "handle.h" + +static char *get_filename(const char *url) { +	char *filename = strrchr(url, '/'); +	if(filename != NULL) { +		filename++; +	} +	return(filename); +} + +static char *get_destfile(const char *path, const char *filename) { +	char *destfile; +	/* len = localpath len + filename len + null */ +	int len = strlen(path) + strlen(filename) + 1; +	CALLOC(destfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); +	snprintf(destfile, len, "%s%s", path, filename); + +	return(destfile); +} + +static char *get_tempfile(const char *path, const char *filename) { +	char *tempfile; +	/* len = localpath len + filename len + '.part' len + null */ +	int len = strlen(path) + strlen(filename) + 6; +	CALLOC(tempfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); +	snprintf(tempfile, len, "%s%s.part", path, filename); + +	return(tempfile); +} + +#if defined(INTERNAL_DOWNLOAD) +/* Build a 'struct url' from an url. */ +static struct url *url_for_string(const char *url) +{ +	struct url *ret = NULL; +	ret = downloadParseURL(url); +	if(!ret) { +		_alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); +		RET_ERR(PM_ERR_SERVER_BAD_URL, NULL); +	} + +	/* if no URL scheme specified, assume HTTP */ +	if(strlen(ret->scheme) == 0) { +		_alpm_log(PM_LOG_WARNING, _("url scheme not specified, assuming HTTP\n")); +		strcpy(ret->scheme, SCHEME_HTTP); +	} +	/* add a user & password for anonymous FTP */ +	if(strcmp(ret->scheme,SCHEME_FTP) == 0 && strlen(ret->user) == 0) { +		strcpy(ret->user, "anonymous"); +		strcpy(ret->pwd, "libalpm@guest"); +	} + +	return(ret); +} + +static int download_internal(const char *url, const char *localpath, +		time_t mtimeold, time_t *mtimenew) { +	FILE *dlf, *localf = NULL; +	struct url_stat ust; +	struct stat st; +	int chk_resume = 0; +	int dl_thisfile = 0; +	char *tempfile, *destfile, *filename; +	int ret = 0; +	struct url *fileurl = url_for_string(url); + +	if(!fileurl) { +		return(-1); +	} + +	filename = get_filename(url); +	if(!filename) { +		return(-1); +	} +	destfile = get_destfile(localpath, filename); +	tempfile = get_tempfile(localpath, filename); + +	/* pass the raw filename for passing to the callback function */ +	_alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", filename); + +	if(stat(tempfile, &st) == 0 && st.st_size > 0) { +		_alpm_log(PM_LOG_DEBUG, "existing file found, using it\n"); +		fileurl->offset = (off_t)st.st_size; +		dl_thisfile = st.st_size; +		localf = fopen(tempfile, "ab"); +		chk_resume = 1; +	} else { +		fileurl->offset = (off_t)0; +		dl_thisfile = 0; +	} + +	/* libdownload does not reset the error code, reset it in +	 * the case of previous errors */ +	downloadLastErrCode = 0; + +	/* 10s timeout - TODO make a config option */ +	downloadTimeout = 10000; + +	dlf = downloadXGet(fileurl, &ust, (handle->nopassiveftp ? "" : "p")); + +	if(downloadLastErrCode != 0 || dlf == NULL) { +		const char *host = _("disk"); +		if(strcmp(SCHEME_FILE, fileurl->scheme) != 0) { +			host = fileurl->host; +		} +		pm_errno = PM_ERR_LIBDOWNLOAD; +		_alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), +				filename, host, downloadLastErrString); +		ret = -1; +		goto cleanup; +	} else { +		_alpm_log(PM_LOG_DEBUG, "connected to %s successfully\n", fileurl->host); +	} + +	if(ust.mtime && mtimeold && ust.mtime == mtimeold) { +		_alpm_log(PM_LOG_DEBUG, "mtimes are identical, skipping %s\n", filename); +		ret = 1; +		goto cleanup; +	} + +	if(ust.mtime && mtimenew) { +		*mtimenew = ust.mtime; +	} + +	if(chk_resume && fileurl->offset == 0) { +		_alpm_log(PM_LOG_WARNING, _("cannot resume download, starting over\n")); +		if(localf != NULL) { +			fclose(localf); +			localf = NULL; +		} +	} + +	if(localf == NULL) { +		_alpm_rmrf(tempfile); +		fileurl->offset = (off_t)0; +		dl_thisfile = 0; +		localf = fopen(tempfile, "wb"); +		if(localf == NULL) { /* still null? */ +			_alpm_log(PM_LOG_ERROR, _("cannot write to file '%s'\n"), tempfile); +			ret = -1; +			goto cleanup; +		} +	} + +	/* Progress 0 - initialize */ +	if(handle->dlcb) { +		handle->dlcb(filename, 0, ust.size); +	} + +	int nread = 0; +	char buffer[PM_DLBUF_LEN]; +	while((nread = fread(buffer, 1, PM_DLBUF_LEN, dlf)) > 0) { +		if(ferror(dlf)) { +			pm_errno = PM_ERR_LIBDOWNLOAD; +			_alpm_log(PM_LOG_ERROR, _("error downloading '%s': %s\n"), +					filename, downloadLastErrString); +			ret = -1; +			goto cleanup; +		} + +		int nwritten = 0; +		while(nwritten < nread) { +			nwritten += fwrite(buffer, 1, (nread - nwritten), localf); +			if(ferror(localf)) { +				_alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), +						destfile, strerror(errno)); +				ret = -1; +				goto cleanup; +			} +		} +		dl_thisfile += nread; + +		if(handle->dlcb) { +			handle->dlcb(filename, dl_thisfile, ust.size); +		} +	} +	/* probably safer to close the file descriptors now before renaming the file, +	 * for example to make sure the buffers are flushed. +	 */ +	fclose(localf); +	localf = NULL; +	fclose(dlf); +	dlf = NULL; + +	rename(tempfile, destfile); +	ret = 0; + +cleanup: +	FREE(tempfile); +	FREE(destfile); +	if(localf != NULL) { +		fclose(localf); +	} +	if(dlf != NULL) { +		fclose(dlf); +	} +	downloadFreeURL(fileurl); +	return(ret); +} +#endif + +static int download_external(const char *url, const char *localpath, +		time_t mtimeold, time_t *mtimenew) { +	int ret = 0; +	int retval; +	int usepart = 0; +	char *ptr1, *ptr2; +	char origCmd[PATH_MAX]; +	char parsedCmd[PATH_MAX] = ""; +	char cwd[PATH_MAX]; +	char *destfile, *tempfile, *filename; + +	if(!handle->xfercommand) { +		RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); +	} + +	filename = get_filename(url); +	if(!filename) { +		RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); +	} +	destfile = get_destfile(localpath, filename); +	tempfile = get_tempfile(localpath, filename); + +	/* replace all occurrences of %o with fn.part */ +	strncpy(origCmd, handle->xfercommand, sizeof(origCmd)); +	ptr1 = origCmd; +	while((ptr2 = strstr(ptr1, "%o"))) { +		usepart = 1; +		ptr2[0] = '\0'; +		strcat(parsedCmd, ptr1); +		strcat(parsedCmd, tempfile); +		ptr1 = ptr2 + 2; +	} +	strcat(parsedCmd, ptr1); +	/* replace all occurrences of %u with the download URL */ +	strncpy(origCmd, parsedCmd, sizeof(origCmd)); +	parsedCmd[0] = '\0'; +	ptr1 = origCmd; +	while((ptr2 = strstr(ptr1, "%u"))) { +		ptr2[0] = '\0'; +		strcat(parsedCmd, ptr1); +		strcat(parsedCmd, url); +		ptr1 = ptr2 + 2; +	} +	strcat(parsedCmd, ptr1); +	/* cwd to the download directory */ +	getcwd(cwd, PATH_MAX); +	if(chdir(localpath)) { +		_alpm_log(PM_LOG_WARNING, _("could not chdir to %s\n"), localpath); +		pm_errno = PM_ERR_EXTERNAL_DOWNLOAD; +		ret = -1; +		goto cleanup; +	} +	/* execute the parsed command via /bin/sh -c */ +	_alpm_log(PM_LOG_DEBUG, "running command: %s\n", parsedCmd); +	retval = system(parsedCmd); + +	if(retval == -1) { +		_alpm_log(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); +		pm_errno = PM_ERR_EXTERNAL_DOWNLOAD; +		ret = -1; +	} else if(retval != 0) { +		/* download failed */ +		_alpm_log(PM_LOG_DEBUG, "XferCommand command returned non-zero status " +				"code (%d)\n", retval); +		ret = -1; +	} else { +		/* download was successful */ +		if(usepart) { +			rename(tempfile, destfile); +		} +		ret = 0; +	} + +cleanup: +	chdir(cwd); +	if(ret == -1) { +		/* hack to let an user the time to cancel a download */ +		sleep(2); +	} +	FREE(destfile); +	FREE(tempfile); + +	return(ret); +} + +static int download(const char *url, const char *localpath, +		time_t mtimeold, time_t *mtimenew) { +	int ret; +	const char *proto = "file://"; +	int len = strlen(proto); +	if(strncmp(url, proto, len) == 0) { +		/* we can simply grab an absolute path from the file:// url by starting +		 * our path at the char following the proto (the root '/') +		 */ +		const char *sourcefile = url + len; +		const char *filename = get_filename(url); +		char *destfile = get_destfile(localpath, filename); + +		ret = _alpm_copyfile(sourcefile, destfile); +		FREE(destfile); +		/* copyfile returns 1 on failure, we want to return -1 on failure */ +		return(ret ? -1 : 0); +	} + +	/* We have a few things to take into account here. +	 * 1. If we have both internal/external available, choose based on +	 * whether xfercommand is populated. +	 * 2. If we only have external available, we should first check +	 * if a command was provided before we drop into download_external. +	 */ +	if(handle->xfercommand == NULL) { +#if defined(INTERNAL_DOWNLOAD) +		ret = download_internal(url, localpath, mtimeold, mtimenew); +#else +		RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); +#endif +	} else { +		ret = download_external(url, localpath, mtimeold, mtimenew); +	} +	return(ret); +} + +/* + * Download a single file + *   - if mtimeold is non-NULL, then only download the file if it's different + *     than mtimeold. + *   - if *mtimenew is non-NULL, it will be filled with the mtime of the remote + *     file. + * + * RETURN:  0 for successful download + *          1 if the mtimes are identical + *         -1 on error + */ +int _alpm_download_single_file(const char *filename, +		alpm_list_t *servers, const char *localpath, +		time_t mtimeold, time_t *mtimenew) +{ +	alpm_list_t *i; +	int ret = -1; + +	for(i = servers; i; i = i->next) { +		const char *server = i->data; +		char *fileurl = NULL; +		int len; + +		/* print server + filename into a buffer */ +		len = strlen(server) + strlen(filename) + 2; +		CALLOC(fileurl, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); +		snprintf(fileurl, len, "%s/%s", server, filename); + +		ret = download(fileurl, localpath, mtimeold, mtimenew); +		FREE(fileurl); +		if(ret != -1) { +			break; +		} +	} + +	return(ret); +} + +int _alpm_download_files(alpm_list_t *files, +		alpm_list_t *servers, const char *localpath) +{ +	int ret = 0; +	alpm_list_t *lp; + +	for(lp = files; lp; lp = lp->next) { +		char *filename = lp->data; +		if(_alpm_download_single_file(filename, servers, +					localpath, 0, NULL) == -1) { +			ret++; +		} +	} + +	return(ret); +} + +/** Fetch a remote pkg. + * @param url URL of the package to download + * @return the downloaded filepath on success, NULL on error + * @addtogroup alpm_misc + */ +char SYMEXPORT *alpm_fetch_pkgurl(const char *url) +{ +	char *filename, *filepath; +	const char *cachedir; +	int ret; + +	ALPM_LOG_FUNC; + +	filename = get_filename(url); + +	/* find a valid cache dir to download to */ +	cachedir = _alpm_filecache_setup(); + +	/* download the file */ +	ret = download(url, cachedir, 0, NULL); +	if(ret == -1) { +		_alpm_log(PM_LOG_WARNING, _("failed to download %s\n"), url); +		return(NULL); +	} +	_alpm_log(PM_LOG_DEBUG, "successfully downloaded %s\n", url); + +	/* we should be able to find the file the second time around */ +	filepath = _alpm_filecache_find(filename); +	return(filepath); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/error.h b/lib/libalpm/dload.h index e417195f..eb642522 100644 --- a/lib/libalpm/error.h +++ b/lib/libalpm/dload.h @@ -1,7 +1,7 @@  /* - *  error.h + *  dload.h   * - *  Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> + *  Copyright (c) 2002-2008 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -16,13 +16,23 @@   *  You should have received a copy of the GNU General Public License   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifndef _ALPM_ERROR_H -#define _ALPM_ERROR_H +#ifndef _ALPM_DLOAD_H +#define _ALPM_DLOAD_H -#define RET_ERR(err, ret) do { pm_errno = (err); \ -	_alpm_log(PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerrorlast()); \ -	return(ret); } while(0) +#include "alpm_list.h" +#include "alpm.h" -#endif /* _ALPM_ERROR_H */ +#include <time.h> + +#define PM_DLBUF_LEN (1024 * 10) + +int _alpm_download_single_file(const char *filename, +		alpm_list_t *servers, const char *localpath, +		time_t mtimeold, time_t *mtimenew); + +int _alpm_download_files(alpm_list_t *files, +		alpm_list_t *servers, const char *localpath); + +#endif /* _ALPM_DLOAD_H */  /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index a68340ad..05caf8ec 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -1,10 +1,7 @@  /*   *  error.c   * - *  Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> - *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> - *  Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> - *  Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> + *  Copyright (c) 2002-2008 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -22,12 +19,28 @@  #include "config.h" +/* TODO: needed for the libfetch stuff, unfortunately- we should kill it */ +#include <stdio.h> +#include <limits.h> +/* the following two are needed on BSD for libfetch */ +#if defined(HAVE_SYS_SYSLIMITS_H) +#include <sys/syslimits.h> /* PATH_MAX */ +#endif +#if defined(HAVE_SYS_PARAM_H) +#include <sys/param.h> /* MAXHOSTNAMELEN */ +#endif + +#if defined(HAVE_LIBDOWNLOAD) +#include <download.h> /* downloadLastErrString */ +#elif defined(HAVE_LIBFETCH) +#include <fetch.h> /* fetchLastErrString */ +#define downloadLastErrString fetchLastErrString +#endif +  /* libalpm */ -#include "error.h"  #include "util.h"  #include "alpm.h" -/* TODO does this really need a file all on its own? */  const char SYMEXPORT *alpm_strerrorlast(void)  {  	return alpm_strerror(pm_errno); @@ -74,13 +87,6 @@ const char SYMEXPORT *alpm_strerror(int err)  		/* Servers */  		case PM_ERR_SERVER_BAD_URL:  			return _("invalid url for server"); -		/* Configuration */ -		case PM_ERR_OPT_LOGFILE: -		case PM_ERR_OPT_DBPATH: -		case PM_ERR_OPT_LOCALDB: -		case PM_ERR_OPT_SYNCDB: -		case PM_ERR_OPT_USESYSLOG: -			return _("could not set parameter");  		/* Transactions */  		case PM_ERR_TRANS_NOT_NULL:  			return _("transaction already initialized"); @@ -109,21 +115,17 @@ const char SYMEXPORT *alpm_strerror(int err)  			return _("cannot open package file");  		case PM_ERR_PKG_LOAD:  			return _("cannot load package data"); -		case PM_ERR_PKG_INSTALLED: -			return _("package already installed");  		case PM_ERR_PKG_CANT_FRESH:  			return _("package not installed or lesser version");  		case PM_ERR_PKG_CANT_REMOVE:  			return _("cannot remove all files for package");  		case PM_ERR_PKG_INVALID_NAME: -			return _("package name is not valid"); -		case PM_ERR_PKG_CORRUPTED: -			return _("corrupted package"); +			return _("package filename is not valid");  		case PM_ERR_PKG_REPO_NOT_FOUND:  			return _("no such repository");  		/* Deltas */ -		case PM_ERR_DLT_CORRUPTED: -			return _("corrupted delta"); +		case PM_ERR_DLT_INVALID: +			return _("invalid or corrupted delta");  		case PM_ERR_DLT_PATCHFAILED:  			return _("delta patch failed");  		/* Groups */ @@ -141,16 +143,26 @@ const char SYMEXPORT *alpm_strerror(int err)  			return _("user aborted the operation");  		case PM_ERR_INTERNAL_ERROR:  			return _("internal error"); -		case PM_ERR_LIBARCHIVE_ERROR: -			return _("libarchive error");  		case PM_ERR_PKG_HOLD:  			/* TODO wow this is not descriptive at all... what does this mean? */  			return _("not confirmed");  		case PM_ERR_INVALID_REGEX:  			return _("invalid regular expression"); -		/* Downloading */ -		case PM_ERR_CONNECT_FAILED: -			return _("connection to remote host failed"); +		/* Errors from external libraries- our own wrapper error */ +		case PM_ERR_LIBARCHIVE: +			/* it would be nice to use archive_error_string() here, but that +			 * requires the archive struct, so we can't. Just use a generic +			 * error string instead. */ +			return _("libarchive error"); +		case PM_ERR_LIBDOWNLOAD: +#if defined(INTERNAL_DOWNLOAD) +			return downloadLastErrString; +#else +			/* obviously shouldn't get here... */ +			return _("download library error"); +#endif +		case PM_ERR_EXTERNAL_DOWNLOAD: +			return _("error invoking external downloader");  		/* Unknown error! */  		default:  			return _("unexpected error"); diff --git a/lib/libalpm/graph.h b/lib/libalpm/graph.h new file mode 100644 index 00000000..3078e25f --- /dev/null +++ b/lib/libalpm/graph.h @@ -0,0 +1,56 @@ +/* + *  graph.h - helpful graph structure and setup/teardown methods + * + *  Copyright (c) 2002-2008 by Judd Vinet <jvinet@zeroflux.org> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "alpm_list.h" +#include "util.h" /* MALLOC() */ +#include "alpm.h" + +struct __pmgraph_t { +	char state; /* 0: untouched, -1: entered, other: leaving time */ +	void *data; +	unsigned long int weight; /* weight of the node */ +	struct __pmgraph_t *parent; /* where did we come from? */ +	alpm_list_t *children; +	alpm_list_t *childptr; /* points to a child in children list */ +}; +typedef struct __pmgraph_t pmgraph_t; + +static pmgraph_t *_alpm_graph_new(void) +{ +	pmgraph_t *graph = NULL; + +	MALLOC(graph, sizeof(pmgraph_t), RET_ERR(PM_ERR_MEMORY, NULL)); + +	if(graph) { +		graph->state = 0; +		graph->data = NULL; +		graph->parent = NULL; +		graph->children = NULL; +		graph->childptr = NULL; +	} +	return(graph); +} + +static void _alpm_graph_free(void *data) +{ +	pmgraph_t *graph = data; +	alpm_list_free(graph->children); +	free(graph); +} + diff --git a/lib/libalpm/group.c b/lib/libalpm/group.c index 050bcbd5..1cc379c6 100644 --- a/lib/libalpm/group.c +++ b/lib/libalpm/group.c @@ -27,17 +27,17 @@  #include "group.h"  #include "alpm_list.h"  #include "util.h" -#include "error.h"  #include "log.h"  #include "alpm.h" -pmgrp_t *_alpm_grp_new() +pmgrp_t *_alpm_grp_new(const char *name)  {  	pmgrp_t* grp;  	ALPM_LOG_FUNC;  	CALLOC(grp, 1, sizeof(pmgrp_t), RET_ERR(PM_ERR_MEMORY, NULL)); +	STRDUP(grp->name, name, RET_ERR(PM_ERR_MEMORY, NULL));  	return(grp);  } @@ -50,7 +50,9 @@ void _alpm_grp_free(pmgrp_t *grp)  		return;  	} -	FREELIST(grp->packages); +	FREE(grp->name); +	/* do NOT free the contents of the list, just the nodes */ +	alpm_list_free(grp->packages);  	FREE(grp);  } @@ -74,7 +76,7 @@ const char SYMEXPORT *alpm_grp_get_name(const pmgrp_t *grp)  	return grp->name;  } -const alpm_list_t SYMEXPORT *alpm_grp_get_pkgs(const pmgrp_t *grp) +alpm_list_t SYMEXPORT *alpm_grp_get_pkgs(const pmgrp_t *grp)  {  	ALPM_LOG_FUNC; diff --git a/lib/libalpm/group.h b/lib/libalpm/group.h index 88fc8b32..5f8fdec4 100644 --- a/lib/libalpm/group.h +++ b/lib/libalpm/group.h @@ -19,17 +19,16 @@  #ifndef _ALPM_GROUP_H  #define _ALPM_GROUP_H -/* Groups */ -#define GRP_NAME_LEN 256 -  #include "alpm.h"  struct __pmgrp_t { -	char name[GRP_NAME_LEN]; -	alpm_list_t *packages; /* List of strings */ +	/** group name */ +	char *name; +	/** list of pmpkg_t packages */ +	alpm_list_t *packages;  }; -pmgrp_t *_alpm_grp_new(void); +pmgrp_t *_alpm_grp_new(const char *name);  void _alpm_grp_free(pmgrp_t *grp);  int _alpm_grp_cmp(const void *g1, const void *g2); diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 36822285..247ef71d 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -36,10 +36,8 @@  #include "alpm_list.h"  #include "util.h"  #include "log.h" -#include "error.h"  #include "trans.h"  #include "alpm.h" -#include "server.h"  /* global var for handle (private to libalpm) */  pmhandle_t *handle = NULL; diff --git a/lib/libalpm/log.c b/lib/libalpm/log.c index 4445f935..3ba5042c 100644 --- a/lib/libalpm/log.c +++ b/lib/libalpm/log.c @@ -30,7 +30,6 @@  #include "log.h"  #include "handle.h"  #include "util.h" -#include "error.h"  #include "alpm.h"  /** \addtogroup alpm_log Logging Functions diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 287c2ce4..ffaa96b3 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -42,7 +42,6 @@  #include "alpm_list.h"  #include "log.h"  #include "util.h" -#include "error.h"  #include "db.h"  #include "cache.h"  #include "delta.h" @@ -105,8 +104,7 @@ int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg)  int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg)  {  	char *fpath; -	char *md5sum = NULL; -	int retval = 0; +	int retval;  	ALPM_LOG_FUNC; @@ -116,28 +114,16 @@ int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg)  	ASSERT(pkg->origin_data.db != handle->db_local, RET_ERR(PM_ERR_PKG_INVALID, -1));  	fpath = _alpm_filecache_find(alpm_pkg_get_filename(pkg)); -	md5sum = alpm_get_md5sum(fpath); -	if(md5sum == NULL) { -		_alpm_log(PM_LOG_ERROR, _("could not get md5sum for package %s-%s\n"), -							alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); -		pm_errno = PM_ERR_NOT_A_FILE; +	retval = _alpm_test_md5sum(fpath, alpm_pkg_get_md5sum(pkg)); + +	if(retval == 0) { +		return(0); +	} else if (retval == 1) { +		pm_errno = PM_ERR_PKG_INVALID;  		retval = -1; -	} else { -		if(strcmp(md5sum, alpm_pkg_get_md5sum(pkg)) == 0) { -			_alpm_log(PM_LOG_DEBUG, "md5sums for package %s-%s match\n", -								alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); -		} else { -			_alpm_log(PM_LOG_ERROR, _("md5sums do not match for package %s-%s\n"), -								alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); -			pm_errno = PM_ERR_PKG_INVALID; -			retval = -1; -		}  	} -	FREE(fpath); -	FREE(md5sum); -  	return(retval);  } @@ -166,17 +152,6 @@ const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg)  		_alpm_db_read(pkg->origin_data.db, pkg, INFRQ_DESC);  	} -	if(!strlen(pkg->filename)) { -		/* construct the file name, it's not in the desc file */ -		if(pkg->arch && strlen(pkg->arch) > 0) { -			snprintf(pkg->filename, PKG_FILENAME_LEN, "%s-%s-%s" PKGEXT, -			         pkg->name, pkg->version, pkg->arch); -		} else { -			snprintf(pkg->filename, PKG_FILENAME_LEN, "%s-%s" PKGEXT, -			         pkg->name, pkg->version); -		} -	} -  	return pkg->filename;  } @@ -520,7 +495,7 @@ void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg)  		int ret = ARCHIVE_OK;  		if((archive = archive_read_new()) == NULL) { -			RET_ERR(PM_ERR_LIBARCHIVE_ERROR, NULL); +			RET_ERR(PM_ERR_LIBARCHIVE, NULL);  		}  		archive_read_support_compression_all(archive); @@ -756,15 +731,12 @@ pmpkg_t *_alpm_pkg_new(const char *name, const char *version)  	CALLOC(pkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); -	if(name && name[0] != 0) { -		strncpy(pkg->name, name, PKG_NAME_LEN); -	} else { -		pkg->name[0] = '\0'; +	if(name) { +		STRDUP(pkg->name, name, RET_ERR(PM_ERR_MEMORY, pkg));  	} -	if(version && version[0] != 0) { -		strncpy(pkg->version, version, PKG_VERSION_LEN); -	} else { -		pkg->version[0] = '\0'; + +	if(version) { +		STRDUP(pkg->version, version, RET_ERR(PM_ERR_MEMORY, pkg));  	}  	return(pkg); @@ -772,31 +744,51 @@ pmpkg_t *_alpm_pkg_new(const char *name, const char *version)  pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg)  { -	pmpkg_t* newpkg; +	pmpkg_t *newpkg; +	alpm_list_t *i;  	ALPM_LOG_FUNC;  	CALLOC(newpkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); -	memcpy(newpkg, pkg, sizeof(pmpkg_t)); +	STRDUP(newpkg->filename, pkg->filename, RET_ERR(PM_ERR_MEMORY, newpkg)); +	STRDUP(newpkg->name, pkg->name, RET_ERR(PM_ERR_MEMORY, newpkg)); +	STRDUP(newpkg->version, pkg->version, RET_ERR(PM_ERR_MEMORY, newpkg)); +	STRDUP(newpkg->desc, pkg->desc, RET_ERR(PM_ERR_MEMORY, newpkg)); +	STRDUP(newpkg->url, pkg->url, RET_ERR(PM_ERR_MEMORY, newpkg)); +	newpkg->builddate = pkg->builddate; +	newpkg->installdate = pkg->installdate; +	STRDUP(newpkg->packager, pkg->packager, RET_ERR(PM_ERR_MEMORY, newpkg)); +	STRDUP(newpkg->md5sum, pkg->md5sum, RET_ERR(PM_ERR_MEMORY, newpkg)); +	STRDUP(newpkg->arch, pkg->arch, RET_ERR(PM_ERR_MEMORY, newpkg)); +	newpkg->size = pkg->size; +	newpkg->isize = pkg->isize; +	newpkg->scriptlet = pkg->scriptlet; +	newpkg->force = pkg->force; +	newpkg->reason = pkg->reason; +  	newpkg->licenses   = alpm_list_strdup(alpm_pkg_get_licenses(pkg)); -	newpkg->conflicts  = alpm_list_strdup(alpm_pkg_get_conflicts(pkg)); +	newpkg->replaces   = alpm_list_strdup(alpm_pkg_get_replaces(pkg)); +	newpkg->groups     = alpm_list_strdup(alpm_pkg_get_groups(pkg));  	newpkg->files      = alpm_list_strdup(alpm_pkg_get_files(pkg));  	newpkg->backup     = alpm_list_strdup(alpm_pkg_get_backup(pkg)); -	newpkg->depends    = alpm_list_copy_data(alpm_pkg_get_depends(pkg), -	                                         sizeof(pmdepend_t)); +	for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { +		newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data)); +	}  	newpkg->optdepends = alpm_list_strdup(alpm_pkg_get_optdepends(pkg)); -	newpkg->groups     = alpm_list_strdup(alpm_pkg_get_groups(pkg)); +	newpkg->conflicts  = alpm_list_strdup(alpm_pkg_get_conflicts(pkg));  	newpkg->provides   = alpm_list_strdup(alpm_pkg_get_provides(pkg)); -	newpkg->replaces   = alpm_list_strdup(alpm_pkg_get_replaces(pkg));  	newpkg->deltas     = alpm_list_copy_data(alpm_pkg_get_deltas(pkg), -	                                         sizeof(pmdelta_t)); +																					 sizeof(pmdelta_t)); +  	/* internal */ +	newpkg->origin = pkg->origin;  	if(newpkg->origin == PKG_FROM_FILE) {  		newpkg->origin_data.file = strdup(pkg->origin_data.file);  	} else {  		newpkg->origin_data.db = pkg->origin_data.db;  	} +	newpkg->infolevel = pkg->infolevel;  	return(newpkg);  } @@ -809,16 +801,28 @@ void _alpm_pkg_free(pmpkg_t *pkg)  		return;  	} +	FREE(pkg->filename); +	FREE(pkg->name); +	FREE(pkg->version); +	FREE(pkg->desc); +	FREE(pkg->url); +	FREE(pkg->packager); +	FREE(pkg->md5sum); +	FREE(pkg->arch);  	FREELIST(pkg->licenses); +	FREELIST(pkg->replaces); +	FREELIST(pkg->groups);  	FREELIST(pkg->files);  	FREELIST(pkg->backup); -	FREELIST(pkg->depends); +	alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free); +	alpm_list_free(pkg->depends);  	FREELIST(pkg->optdepends);  	FREELIST(pkg->conflicts); -	FREELIST(pkg->groups);  	FREELIST(pkg->provides); -	FREELIST(pkg->replaces); -	FREELIST(pkg->deltas); +	alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free); +	alpm_list_free(pkg->deltas); +	alpm_list_free(pkg->delta_path); +  	if(pkg->origin == PKG_FROM_FILE) {  		FREE(pkg->origin_data.file);  	} @@ -866,15 +870,18 @@ int _alpm_pkg_cmp(const void *p1, const void *p2)  	return(strcmp(alpm_pkg_get_name(pk1), alpm_pkg_get_name(pk2)));  } -/* Parses the package description file for the current package - * TODO: this should ALL be in a backend interface (be_files), we should - *       be dealing with the abstracted concepts only in this file +int _alpm_pkgname_pkg_cmp(const void *pkgname, const void *package) +{ +	return(strcmp(alpm_pkg_get_name((pmpkg_t *) package), (char *) pkgname)); +} + + +/* Parses the package description file for the current package. This + * is handed the struct archive when the .PKGINFO file is open.   * Returns: 0 on success, 1 on error - *   */ -static int parse_descfile(const char *descfile, pmpkg_t *info) +static int parse_descfile(struct archive *a, pmpkg_t *info)  { -	FILE* fp = NULL;  	char line[PATH_MAX];  	char *ptr = NULL;  	char *key = NULL; @@ -882,13 +889,8 @@ static int parse_descfile(const char *descfile, pmpkg_t *info)  	ALPM_LOG_FUNC; -	if((fp = fopen(descfile, "r")) == NULL) { -		_alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), descfile, strerror(errno)); -		return(-1); -	} - -	while(!feof(fp)) { -		fgets(line, PATH_MAX, fp); +	/* loop until we reach EOF (where archive_fgets will return NULL) */ +	while(_alpm_archive_fgets(line, PATH_MAX, a) != NULL) {  		linenum++;  		_alpm_strtrim(line);  		if(strlen(line) == 0 || line[0] == '#') { @@ -898,26 +900,26 @@ static int parse_descfile(const char *descfile, pmpkg_t *info)  		key = strsep(&ptr, "=");  		if(key == NULL || ptr == NULL) {  			_alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", -								info->name[0] != '\0' ? info->name : "error", linenum); +								info->name ? info->name : "error", linenum);  		} else { -			_alpm_strtrim(key); -			_alpm_strtrim(ptr); +			key = _alpm_strtrim(key); +			ptr = _alpm_strtrim(ptr);  			if(!strcmp(key, "pkgname")) { -				strncpy(info->name, ptr, sizeof(info->name)); +				STRDUP(info->name, ptr, RET_ERR(PM_ERR_MEMORY, -1));  			} else if(!strcmp(key, "pkgver")) { -				strncpy(info->version, ptr, sizeof(info->version)); +				STRDUP(info->version, ptr, RET_ERR(PM_ERR_MEMORY, -1));  			} else if(!strcmp(key, "pkgdesc")) { -				strncpy(info->desc, ptr, sizeof(info->desc)); +				STRDUP(info->desc, ptr, RET_ERR(PM_ERR_MEMORY, -1));  			} else if(!strcmp(key, "group")) {  				info->groups = alpm_list_add(info->groups, strdup(ptr));  			} else if(!strcmp(key, "url")) { -				strncpy(info->url, ptr, sizeof(info->url)); +				STRDUP(info->url, ptr, RET_ERR(PM_ERR_MEMORY, -1));  			} else if(!strcmp(key, "license")) {  				info->licenses = alpm_list_add(info->licenses, strdup(ptr));  			} else if(!strcmp(key, "builddate")) {  				char first = tolower(ptr[0]);  				if(first > 'a' && first < 'z') { -					struct tm tmp_tm = {0}; //initialize to null incase of failure +					struct tm tmp_tm = {0}; //initialize to null in case of failure  					setlocale(LC_TIME, "C");  					strptime(ptr, "%a %b %e %H:%M:%S %Y", &tmp_tm);  					info->builddate = mktime(&tmp_tm); @@ -926,14 +928,14 @@ static int parse_descfile(const char *descfile, pmpkg_t *info)  					info->builddate = atol(ptr);  				}  			} else if(!strcmp(key, "packager")) { -				strncpy(info->packager, ptr, sizeof(info->packager)); +				STRDUP(info->packager, ptr, RET_ERR(PM_ERR_MEMORY, -1));  			} else if(!strcmp(key, "arch")) { -				strncpy(info->arch, ptr, sizeof(info->arch)); +				STRDUP(info->arch, ptr, RET_ERR(PM_ERR_MEMORY, -1));  			} else if(!strcmp(key, "size")) {  				/* size in the raw package is uncompressed (installed) size */  				info->isize = atol(ptr);  			} else if(!strcmp(key, "depend")) { -				pmdepend_t *dep = alpm_splitdep(ptr); +				pmdepend_t *dep = _alpm_splitdep(ptr);  				info->depends = alpm_list_add(info->depends, dep);  			} else if(!strcmp(key, "optdepend")) {  				info->optdepends = alpm_list_add(info->optdepends, strdup(ptr)); @@ -947,13 +949,11 @@ static int parse_descfile(const char *descfile, pmpkg_t *info)  				info->backup = alpm_list_add(info->backup, strdup(ptr));  			} else {  				_alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", -									info->name[0] != '\0' ? info->name : "error", linenum); +									info->name ? info->name : "error", linenum);  			}  		}  		line[0] = '\0';  	} -	fclose(fp); -	unlink(descfile);  	return(0);  } @@ -973,8 +973,6 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)  	struct archive *archive;  	struct archive_entry *entry;  	pmpkg_t *info = NULL; -	char *descfile = NULL; -	int fd = -1;  	struct stat st;  	ALPM_LOG_FUNC; @@ -984,7 +982,7 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)  	}  	if((archive = archive_read_new()) == NULL) { -		RET_ERR(PM_ERR_LIBARCHIVE_ERROR, NULL); +		RET_ERR(PM_ERR_LIBARCHIVE, NULL);  	}  	archive_read_support_compression_all(archive); @@ -1005,48 +1003,28 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)  		info->size = st.st_size;  	} -	/* TODO there is no reason to make temp files to read -	 * from a libarchive archive, it can be done by reading -	 * directly from the archive -	 * See: archive_read_data_into_buffer -	 * requires changes 'parse_descfile' as well -	 * */ -  	/* If full is false, only read through the archive until we find our needed  	 * metadata. If it is true, read through the entire archive, which serves  	 * as a verfication of integrity and allows us to create the filelist. */  	while((ret = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) {  		const char *entry_name = archive_entry_pathname(entry); -		/* NOTE: we used to look for .FILELIST, but it is easier (and safer) for -		 * us to just generate this on our own. */  		if(strcmp(entry_name, ".PKGINFO") == 0) { -			/* extract this file into /tmp. it has info for us */ -			descfile = strdup("/tmp/alpm_XXXXXX"); -			fd = mkstemp(descfile); -			if(archive_read_data_into_fd(archive, fd) != ARCHIVE_OK) { -				_alpm_log(PM_LOG_ERROR, _("error extracting package description file to %s\n"), -						descfile); -				goto pkg_invalid; -			}  			/* parse the info file */ -			if(parse_descfile(descfile, info) == -1) { +			if(parse_descfile(archive, info) != 0) {  				_alpm_log(PM_LOG_ERROR, _("could not parse package description file in %s\n"),  						pkgfile);  				goto pkg_invalid;  			} -			if(!strlen(info->name)) { +			if(info->name == NULL || strlen(info->name) == 0) {  				_alpm_log(PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile);  				goto pkg_invalid;  			} -			if(!strlen(info->version)) { +			if(info->version == NULL || strlen(info->version) == 0) {  				_alpm_log(PM_LOG_ERROR, _("missing package version in %s\n"), pkgfile);  				goto pkg_invalid;  			}  			config = 1; -			unlink(descfile); -			FREE(descfile); -			close(fd);  			continue;  		} else if(strcmp(entry_name,  ".INSTALL") == 0) {  			info->scriptlet = 1; @@ -1061,7 +1039,7 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)  		if(archive_read_data_skip(archive)) {  			_alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"),  					pkgfile, archive_error_string(archive)); -			pm_errno = PM_ERR_LIBARCHIVE_ERROR; +			pm_errno = PM_ERR_LIBARCHIVE;  			goto error;  		} @@ -1074,7 +1052,7 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)  	if(ret != ARCHIVE_EOF && ret != ARCHIVE_OK) { /* An error occured */  		_alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"),  				pkgfile, archive_error_string(archive)); -		pm_errno = PM_ERR_LIBARCHIVE_ERROR; +		pm_errno = PM_ERR_LIBARCHIVE;  		goto error;  	} @@ -1090,13 +1068,13 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)  	info->origin_data.file = strdup(pkgfile);  	if(full) { -		/* "checking for conflicts" requires a sorted list, so we ensure that here */ +		/* "checking for conflicts" requires a sorted list, ensure that here */  		_alpm_log(PM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile);  		info->files = alpm_list_msort(info->files, alpm_list_count(info->files),  				_alpm_str_cmp);  		info->infolevel = INFRQ_ALL;  	} else { -		/* get rid of any partial filelist we may have collected, as it is invalid */ +		/* get rid of any partial filelist we may have collected, it is invalid */  		FREELIST(info->files);  		info->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_DEPENDS;  	} @@ -1105,13 +1083,6 @@ pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full)  pkg_invalid:  	pm_errno = PM_ERR_PKG_INVALID; -	if(descfile) { -		unlink(descfile); -		FREE(descfile); -	} -	if(fd != -1) { -		close(fd); -	}  error:  	_alpm_pkg_free(info);  	archive_read_finish(archive); diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index d6c3eff9..0ba8aac4 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -33,30 +33,17 @@ typedef enum _pmpkgfrom_t {  	PKG_FROM_FILE  } pmpkgfrom_t; -/* Packages */ -#define PKG_FILENAME_LEN 512 -#define PKG_NAME_LEN     256 -#define PKG_VERSION_LEN  64 -#define PKG_FULLNAME_LEN (PKG_NAME_LEN + PKG_VERSION_LEN) -#define PKG_DESC_LEN     512 -#define PKG_URL_LEN      256 -#define PKG_DATE_LEN     32 -#define PKG_TYPE_LEN     32 -#define PKG_PACKAGER_LEN 64 -#define PKG_MD5SUM_LEN   33 -#define PKG_ARCH_LEN     32 -  struct __pmpkg_t { -	char filename[PKG_FILENAME_LEN]; -	char name[PKG_NAME_LEN]; -	char version[PKG_VERSION_LEN]; -	char desc[PKG_DESC_LEN]; -	char url[PKG_URL_LEN]; +	char *filename; +	char *name; +	char *version; +	char *desc; +	char *url;  	time_t builddate;  	time_t installdate; -	char packager[PKG_PACKAGER_LEN]; -	char md5sum[PKG_MD5SUM_LEN]; -	char arch[PKG_ARCH_LEN]; +	char *packager; +	char *md5sum; +	char *arch;  	unsigned long size;  	unsigned long isize;  	unsigned short scriptlet; @@ -83,6 +70,8 @@ struct __pmpkg_t {  		char *file;  	} origin_data;  	pmdbinfrq_t infolevel; +	unsigned long download_size; +	alpm_list_t *delta_path;  };  int _alpm_versioncmp(const char *a, const char *b); @@ -90,6 +79,7 @@ pmpkg_t* _alpm_pkg_new(const char *name, const char *version);  pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg);  void _alpm_pkg_free(pmpkg_t *pkg);  int _alpm_pkg_cmp(const void *p1, const void *p2); +int _alpm_pkgname_pkg_cmp(const void *pkgname, const void *package);  int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg);  pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full);  pmpkg_t *_alpm_pkg_find(const char *needle, alpm_list_t *haystack); diff --git a/lib/libalpm/po/POTFILES.in b/lib/libalpm/po/POTFILES.in index 80130f24..35bd864b 100644 --- a/lib/libalpm/po/POTFILES.in +++ b/lib/libalpm/po/POTFILES.in @@ -10,6 +10,7 @@ lib/libalpm/conflict.c  lib/libalpm/db.c  lib/libalpm/delta.c  lib/libalpm/deps.c +lib/libalpm/dload.c  lib/libalpm/error.c  lib/libalpm/group.c  lib/libalpm/handle.c @@ -17,7 +18,6 @@ lib/libalpm/log.c  lib/libalpm/md5.c  lib/libalpm/package.c  lib/libalpm/remove.c -lib/libalpm/server.c  lib/libalpm/sync.c  lib/libalpm/trans.c  lib/libalpm/util.c diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index a0f9963a..f2e84ef5 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -37,7 +37,6 @@  #include "alpm_list.h"  #include "trans.h"  #include "util.h" -#include "error.h"  #include "log.h"  #include "backup.h"  #include "package.h" @@ -82,6 +81,60 @@ int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)  	return(0);  } +static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db, +		alpm_list_t *lp) +{ +	ALPM_LOG_FUNC; + +	while(lp) { +		alpm_list_t *i; +		for(i = lp; i; i = i->next) { +			pmdepmissing_t *miss = (pmdepmissing_t *)i->data; +			pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target); +			if(info) { +				if(!_alpm_pkg_find(alpm_pkg_get_name(info), trans->packages)) { +					_alpm_log(PM_LOG_DEBUG, "pulling %s in the targets list\n", +							alpm_pkg_get_name(info)); +					trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info)); +				} +			} else { +				_alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"), +									miss->target); +			} +		} +		alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); +		alpm_list_free(lp); +		lp = alpm_checkdeps(db, 1, trans->packages, NULL); +	} +} + +static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, +		alpm_list_t *lp) +{ +	ALPM_LOG_FUNC; + +	/* Remove needed packages (which break dependencies) from the target list */ +	while(lp != NULL) { +		alpm_list_t *i; +		for(i = lp; i; i = i->next) { +			pmdepmissing_t *miss = (pmdepmissing_t *)i->data; +			void *vpkg; +			pmpkg_t *pkg; +			trans->packages = alpm_list_remove(trans->packages, miss->causingpkg, +					_alpm_pkgname_pkg_cmp, &vpkg); +			pkg = vpkg; +			if(pkg) { +				_alpm_log(PM_LOG_WARNING, "removing %s from the target-list\n", +						alpm_pkg_get_name(pkg)); +				_alpm_pkg_free(pkg); +			} +		} +		alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); +		alpm_list_free(lp); +		lp = alpm_checkdeps(db, 1, trans->packages, NULL); +	} +} +  int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)  {  	alpm_list_t *lp; @@ -102,31 +155,19 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)  		_alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n");  		lp = alpm_checkdeps(db, 1, trans->packages, NULL);  		if(lp != NULL) { +  			if(trans->flags & PM_TRANS_FLAG_CASCADE) { -				while(lp) { -					alpm_list_t *i; -					for(i = lp; i; i = i->next) { -						pmdepmissing_t *miss = (pmdepmissing_t *)i->data; -						pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target); -						if(info) { -							if(!_alpm_pkg_find(alpm_pkg_get_name(info), trans->packages)) { -								_alpm_log(PM_LOG_DEBUG, "pulling %s in the targets list\n", -										alpm_pkg_get_name(info)); -								trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info)); -							} -						} else { -							_alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"), -							          miss->target); -						} -					} -					FREELIST(lp); -					lp = alpm_checkdeps(db, 1, trans->packages, NULL); -				} +				remove_prepare_cascade(trans, db, lp); +			} else if (trans->flags & PM_TRANS_FLAG_UNNEEDED) { +				/* Remove needed packages (which would break dependencies) +				 * from the target list */ +				remove_prepare_keep_needed(trans, db, lp);  			} else {  				if(data) {  					*data = lp;  				} else { -					FREELIST(lp); +					alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); +					alpm_list_free(lp);  				}  				RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1);  			} @@ -135,14 +176,14 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)  	/* re-order w.r.t. dependencies */  	_alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); -	lp = _alpm_sortbydeps(trans->packages, PM_TRANS_TYPE_REMOVE); +	lp = _alpm_sortbydeps(trans->packages, 1);  	/* free the old alltargs */  	alpm_list_free(trans->packages);  	trans->packages = lp;  	if(trans->flags & PM_TRANS_FLAG_RECURSE) {  		_alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); -		_alpm_recursedeps(db, trans->packages, 0); +		_alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL);  	}  	if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { diff --git a/lib/libalpm/server.c b/lib/libalpm/server.c deleted file mode 100644 index 4bccf3ca..00000000 --- a/lib/libalpm/server.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - *  server.c - * - *  Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> - * - *  This program is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 2 of the License, or - *  (at your option) any later version. - * - *  This program is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with this program.  If not, see <http://www.gnu.org/licenses/>. - */ - -#include "config.h" - -#include <stdlib.h> -#include <errno.h> -#include <time.h> -#include <string.h> -#include <limits.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <download.h> - -/* libalpm */ -#include "server.h" -#include "alpm_list.h" -#include "error.h" -#include "log.h" -#include "alpm.h" -#include "util.h" -#include "handle.h" -#include "package.h" - -pmserver_t *_alpm_server_new(const char *url) -{ -	struct url *u; -	pmserver_t *server; - -	ALPM_LOG_FUNC; - -	CALLOC(server, 1, sizeof(pmserver_t), RET_ERR(PM_ERR_MEMORY, NULL)); - -	u = downloadParseURL(url); -	if(!u) { -		_alpm_log(PM_LOG_ERROR, _("url '%s' is invalid, ignoring\n"), url); -		RET_ERR(PM_ERR_SERVER_BAD_URL, NULL); -	} -	if(strlen(u->scheme) == 0) { -		_alpm_log(PM_LOG_WARNING, _("url scheme not specified, assuming http\n")); -		strcpy(u->scheme, "http"); -	} - -	if(strcmp(u->scheme,"ftp") == 0 && strlen(u->user) == 0) { -		strcpy(u->user, "anonymous"); -		strcpy(u->pwd, "libalpm@guest"); -	} - -	/* remove trailing slashes, just to clean up the rest of the code */ -	for(int i = strlen(u->doc) - 1; u->doc[i] == '/'; --i) -		u->doc[i] = '\0'; - -  server->s_url = u; - -	return server; -} - -void _alpm_server_free(pmserver_t *server) -{ -	ALPM_LOG_FUNC; - -	if(server == NULL) { -		return; -	} - -	/* free memory */ -	downloadFreeURL(server->s_url); -	FREE(server); -} - -/* remove filename info from "s_url->doc" and return it */ -static char *strip_filename(pmserver_t *server) -{ -	char *p = NULL, *fname = NULL; -	if(!server) { -		return(NULL); -	} - -	p = strrchr(server->s_url->doc, '/'); -	if(p && *(++p)) { -		fname = strdup(p); -		_alpm_log(PM_LOG_DEBUG, "stripping '%s' from '%s'\n", -				fname, server->s_url->doc); -		*p = 0; -	} - -	/* s_url->doc now contains ONLY path information.  return value -	 * if the file information from the original URL */ -	return(fname); -} - -/* Return a 'struct url' for this server, for downloading 'filename'. */ -static struct url *url_for_file(pmserver_t *server, const char *filename) -{ -	struct url *ret = NULL; -	char *doc = NULL; -	int doclen = 0; - -	doclen = strlen(server->s_url->doc) + strlen(filename) + 2; -	CALLOC(doc, doclen, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); - -	snprintf(doc, doclen, "%s/%s", server->s_url->doc, filename); -	ret = downloadMakeURL(server->s_url->scheme, -												server->s_url->host, -												server->s_url->port, -												doc, -												server->s_url->user, -												server->s_url->pwd); -	FREE(doc); -	return(ret); -} - -/* - * Download a list of files from a list of servers - *   - if one server fails, we try the next one in the list - *   - if *dl_total is non-NULL, then it will be used as the starting - *     download amount when TotalDownload is set. It will also be - *     set to the final download amount for the calling function to use. - *   - totalsize is the total download size for use when TotalDownload - *     is set. Use 0 if the total download size is not known. - * - * RETURN:  0 for successful download, 1 on error - */ -int _alpm_downloadfiles(alpm_list_t *servers, const char *localpath, -		alpm_list_t *files, int *dl_total, unsigned long totalsize) -{ -	return(_alpm_downloadfiles_forreal(servers, localpath, files, 0, NULL, -				dl_total, totalsize)); -} - -/* - * This is the real downloadfiles, used directly by sync_synctree() to check - * modtimes on remote files. - *   - if mtime1 is non-NULL, then only download files if they are different - *     than mtime1. - *   - if *mtime2 is non-NULL, it will be filled with the mtime of the remote - *     file. - *   - if *dl_total is non-NULL, then it will be used as the starting - *     download amount when TotalDownload is set. It will also be - *     set to the final download amount for the calling function to use. - *   - totalsize is the total download size for use when TotalDownload - *     is set. Use 0 if the total download size is not known. - * - * RETURN:  0 for successful download - *          1 if the mtimes are identical - *         -1 on error - */ -int _alpm_downloadfiles_forreal(alpm_list_t *servers, const char *localpath, -	alpm_list_t *files, time_t mtime1, time_t *mtime2, int *dl_total, -	unsigned long totalsize) -{ -	int dl_thisfile = 0; -	alpm_list_t *lp; -	int done = 0; -	alpm_list_t *complete = NULL; -	alpm_list_t *i; - -	ALPM_LOG_FUNC; - -	if(files == NULL) { -		return(0); -	} - -	for(i = servers; i && !done; i = i->next) { -		pmserver_t *server = i->data; - -		/* get each file in the list */ -		for(lp = files; lp; lp = lp->next) { -			struct url *fileurl = NULL; -			char realfile[PATH_MAX]; -			char output[PATH_MAX]; -			char *fn = (char *)lp->data; -			char pkgname[PKG_NAME_LEN]; - -			fileurl = url_for_file(server, fn); -			if(!fileurl) { -				return(-1); -			} - -			/* pass the raw filename for passing to the callback function */ -			strncpy(pkgname, fn, PKG_NAME_LEN); -			_alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", pkgname); - -			snprintf(realfile, PATH_MAX, "%s%s", localpath, fn); -			snprintf(output, PATH_MAX, "%s%s.part", localpath, fn); - -			if(alpm_list_find_str(complete, fn)) { -				continue; -			} - -			if(!handle->xfercommand || !strcmp(fileurl->scheme, "file")) { -				FILE *dlf, *localf = NULL; -				struct url_stat ust; -				struct stat st; -				int chk_resume = 0; - -				if(stat(output, &st) == 0 && st.st_size > 0) { -					_alpm_log(PM_LOG_DEBUG, "existing file found, using it\n"); -					fileurl->offset = (off_t)st.st_size; -					dl_thisfile = st.st_size; -					if (dl_total != NULL) { -						*dl_total += st.st_size; -					} -					localf = fopen(output, "a"); -					chk_resume = 1; -				} else { -					fileurl->offset = (off_t)0; -					dl_thisfile = 0; -				} - -				/* libdownload does not reset the error code, reset it in -				 * the case of previous errors */ -				downloadLastErrCode = 0; - -				/* 10s timeout - TODO make a config option */ -				downloadTimeout = 10000; - -				dlf = downloadXGet(fileurl, &ust, (handle->nopassiveftp ? "" : "p")); - -				if(downloadLastErrCode != 0 || dlf == NULL) { -					const char *host = _("disk"); -					if(strcmp(SCHEME_FILE, fileurl->scheme) != 0) { -						host = fileurl->host; -					} -					_alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), -										fn, host, downloadLastErrString); -					if(localf != NULL) { -						fclose(localf); -					} -					/* try the next server */ -					downloadFreeURL(fileurl); -					continue; -				} else { -						_alpm_log(PM_LOG_DEBUG, "connected to %s successfully\n", fileurl->host); -				} - -				if(ust.mtime && mtime1 && ust.mtime == mtime1) { -					_alpm_log(PM_LOG_DEBUG, "mtimes are identical, skipping %s\n", fn); -					complete = alpm_list_add(complete, fn); -					if(localf != NULL) { -						fclose(localf); -					} -					if(dlf != NULL) { -						fclose(dlf); -					} -					downloadFreeURL(fileurl); -					return(1); -				} - -				if(ust.mtime && mtime2) { -					*mtime2 = ust.mtime; -				} - -				if(chk_resume && fileurl->offset == 0) { -					_alpm_log(PM_LOG_WARNING, _("cannot resume download, starting over\n")); -					if(localf != NULL) { -						fclose(localf); -						localf = NULL; -					} -				} - -				if(localf == NULL) { -					_alpm_rmrf(output); -					fileurl->offset = (off_t)0; -					dl_thisfile = 0; -					localf = fopen(output, "w"); -					if(localf == NULL) { /* still null? */ -						_alpm_log(PM_LOG_ERROR, _("cannot write to file '%s'\n"), output); -						if(dlf != NULL) { -							fclose(dlf); -						} -						downloadFreeURL(fileurl); -						return(-1); -					} -				} - -				/* Progress 0 - initialize */ -				if(handle->dlcb) { -					handle->dlcb(pkgname, 0, ust.size, dl_total ? *dl_total : 0, -							totalsize); -				} - -				int nread = 0; -				char buffer[PM_DLBUF_LEN]; -				while((nread = fread(buffer, 1, PM_DLBUF_LEN, dlf)) > 0) { -					if(ferror(dlf)) { -						_alpm_log(PM_LOG_ERROR, _("error downloading '%s': %s\n"), -											fn, downloadLastErrString); -						fclose(localf); -						fclose(dlf); -						downloadFreeURL(fileurl); -						return(-1); -					} - -					int nwritten = 0; -					while(nwritten < nread) { -						nwritten += fwrite(buffer, 1, (nread - nwritten), localf); -						if(ferror(localf)) { -							_alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), -												realfile, strerror(errno)); -							fclose(localf); -							fclose(dlf); -							downloadFreeURL(fileurl); -							return(-1); -						} -					} - -					if(nwritten != nread) { - -					} -					dl_thisfile += nread; -					if (dl_total != NULL) { -						*dl_total += nread; -					} - -					if(handle->dlcb) { -						handle->dlcb(pkgname, dl_thisfile, ust.size, -								dl_total ? *dl_total : 0, totalsize); -					} -				} - -				downloadFreeURL(fileurl); -				fclose(localf); -				fclose(dlf); -				rename(output, realfile); -				complete = alpm_list_add(complete, fn); -			} else { -				int ret; -				int usepart = 0; -				char *ptr1, *ptr2; -				char origCmd[PATH_MAX]; -				char parsedCmd[PATH_MAX] = ""; -				char url[PATH_MAX]; -				char cwd[PATH_MAX]; - -				/* build the full download url */ -				snprintf(url, PATH_MAX, "%s://%s%s", fileurl->scheme, -						fileurl->host, fileurl->doc); -				/* we don't need this anymore */ -				downloadFreeURL(fileurl); - -				/* replace all occurrences of %o with fn.part */ -				strncpy(origCmd, handle->xfercommand, sizeof(origCmd)); -				ptr1 = origCmd; -				while((ptr2 = strstr(ptr1, "%o"))) { -					usepart = 1; -					ptr2[0] = '\0'; -					strcat(parsedCmd, ptr1); -					strcat(parsedCmd, output); -					ptr1 = ptr2 + 2; -				} -				strcat(parsedCmd, ptr1); -				/* replace all occurrences of %u with the download URL */ -				strncpy(origCmd, parsedCmd, sizeof(origCmd)); -				parsedCmd[0] = '\0'; -				ptr1 = origCmd; -				while((ptr2 = strstr(ptr1, "%u"))) { -					ptr2[0] = '\0'; -					strcat(parsedCmd, ptr1); -					strcat(parsedCmd, url); -					ptr1 = ptr2 + 2; -				} -				strcat(parsedCmd, ptr1); -				/* cwd to the download directory */ -				getcwd(cwd, PATH_MAX); -				if(chdir(localpath)) { -					_alpm_log(PM_LOG_WARNING, _("could not chdir to %s\n"), localpath); -					return(PM_ERR_CONNECT_FAILED); -				} -				/* execute the parsed command via /bin/sh -c */ -				_alpm_log(PM_LOG_DEBUG, "running command: %s\n", parsedCmd); -				ret = system(parsedCmd); -				if(ret == -1) { -					_alpm_log(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); -					return(PM_ERR_FORK_FAILED); -				} else if(ret != 0) { -					/* download failed */ -					_alpm_log(PM_LOG_DEBUG, "XferCommand command returned non-zero status code (%d)\n", ret); -				} else { -					/* download was successful */ -					complete = alpm_list_add(complete, fn); -					if(usepart) { -						rename(output, realfile); -					} -				} -				chdir(cwd); -			} -		} - -		if(alpm_list_count(complete) == alpm_list_count(files)) { -			done = 1; -		} -	} -	alpm_list_free(complete); - -	return(done ? 0 : -1); -} - -/** Fetch a remote pkg. - * @param url URL of the package to download - * @return the downloaded filepath on success, NULL on error - * @addtogroup alpm_misc - */ -char SYMEXPORT *alpm_fetch_pkgurl(const char *url) -{ -	pmserver_t *server; -	char *filename, *filepath; -	const char *cachedir; - -	ALPM_LOG_FUNC; - -	if(strstr(url, "://") == NULL) { -		_alpm_log(PM_LOG_DEBUG, "Invalid URL passed to alpm_fetch_pkgurl\n"); -		return(NULL); -	} - -	server = _alpm_server_new(url); -	if(!server) { -		return(NULL); -	} - -	/* strip path information from the filename */ -	filename = strip_filename(server); -	if(!filename) { -		_alpm_log(PM_LOG_ERROR, _("URL does not contain a file for download\n")); -		return(NULL); -	} - -	/* find a valid cache dir to download to */ -	cachedir = _alpm_filecache_setup(); - -	/* TODO this seems like needless complexity just to download one file */ -	alpm_list_t *servers = alpm_list_add(NULL, server); -	alpm_list_t *files = alpm_list_add(NULL, filename); - -	/* download the file */ -	if(_alpm_downloadfiles(servers, cachedir, files, NULL, 0)) { -		_alpm_log(PM_LOG_WARNING, _("failed to download %s\n"), url); -		return(NULL); -	} -	_alpm_log(PM_LOG_DEBUG, "successfully downloaded %s\n", filename); -	alpm_list_free(files); -	alpm_list_free(servers); -	_alpm_server_free(server); - -	/* we should be able to find the file the second time around */ -	filepath = _alpm_filecache_find(filename); -	return(filepath); -} - -/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/server.h b/lib/libalpm/server.h deleted file mode 100644 index b82fcb09..00000000 --- a/lib/libalpm/server.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - *  server.h - * - *  Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> - * - *  This program is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 2 of the License, or - *  (at your option) any later version. - * - *  This program is distributed in the hope that it will be useful, - *  but WITHOUT ANY WARRANTY; without even the implied warranty of - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - *  GNU General Public License for more details. - * - *  You should have received a copy of the GNU General Public License - *  along with this program.  If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef _ALPM_SERVER_H -#define _ALPM_SERVER_H - -#include "alpm_list.h" -#include "alpm.h" - -#include <time.h> -#include <download.h> - -/* Servers */ -struct __pmserver_t { -	/* useless abstraction now? */ -	struct url *s_url; -}; - -#define PM_DLBUF_LEN (1024 * 10) - -pmserver_t *_alpm_server_new(const char *url); -void _alpm_server_free(pmserver_t *server); -int _alpm_downloadfiles(alpm_list_t *servers, const char *localpath, -		alpm_list_t *files, int *dl_total, unsigned long totalsize); -int _alpm_downloadfiles_forreal(alpm_list_t *servers, const char *localpath, -	alpm_list_t *files, time_t mtime1, time_t *mtime2, int *dl_total, -	unsigned long totalsize); - -#endif /* _ALPM_SERVER_H */ - -/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index a927f61b..357b01f2 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -34,7 +34,6 @@  #include "sync.h"  #include "alpm_list.h"  #include "log.h" -#include "error.h"  #include "package.h"  #include "db.h"  #include "cache.h" @@ -44,10 +43,10 @@  #include "util.h"  #include "handle.h"  #include "alpm.h" -#include "server.h" +#include "dload.h"  #include "delta.h" -pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data) +pmsyncpkg_t *_alpm_sync_new(pmpkgreason_t newreason, pmpkg_t *spkg, alpm_list_t *removes)  {  	pmsyncpkg_t *sync; @@ -55,9 +54,9 @@ pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data)  	CALLOC(sync, 1, sizeof(pmsyncpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); -	sync->type = type; +	sync->newreason = newreason;  	sync->pkg = spkg; -	sync->data = data; +	sync->removes = removes;  	return(sync);  } @@ -70,32 +69,11 @@ void _alpm_sync_free(pmsyncpkg_t *sync)  		return;  	} -	/* TODO wow this is ugly */ -	if(sync->type == PM_SYNC_TYPE_REPLACE) { -		alpm_list_free_inner(sync->data, (alpm_list_fn_free)_alpm_pkg_free); -		alpm_list_free(sync->data); -		sync->data = NULL; -	} else { -		_alpm_pkg_free(sync->data); -		sync->data = NULL; -	} +	alpm_list_free(sync->removes); +	sync->removes = NULL;  	FREE(sync);  } -static void synclist_free(alpm_list_t *syncpkgs) -{ -	if(syncpkgs) { -		alpm_list_t *tmp; -		for(tmp = syncpkgs; tmp; tmp = alpm_list_next(tmp)) { -			if(tmp->data) { -				_alpm_sync_free(tmp->data); -			} -		} -		alpm_list_free(syncpkgs); -	} - -} -  /* Find recommended replacements for packages during a sync.   */  static int find_replacements(pmtrans_t *trans, pmdb_t *db_local, @@ -147,27 +125,29 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,  					 * the package to replace.  					 */  					pmsyncpkg_t *sync; -					pmpkg_t *dummy = _alpm_pkg_dup(lpkg); -					if(dummy == NULL) { -						pm_errno = PM_ERR_MEMORY; -						synclist_free(*syncpkgs); -						return(-1); -					} +  					/* check if spkg->name is already in the packages list. */ +					/* TODO: same package name doesn't mean same package */  					sync = _alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg));  					if(sync) { -						/* found it -- just append to the replaces list */ -						sync->data = alpm_list_add(sync->data, dummy); +						/* found it -- just append to the removes list */ +						sync->removes = alpm_list_add(sync->removes, lpkg); +						/* check the to-be-replaced package's reason field */ +						if(lpkg->reason == PM_PKG_REASON_EXPLICIT) { +							sync->newreason = PM_PKG_REASON_EXPLICIT; +						}  					} else {  						/* none found -- enter pkg into the final sync list */ -						sync = _alpm_sync_new(PM_SYNC_TYPE_REPLACE, spkg, NULL); +						/* copy over reason */ +						sync = _alpm_sync_new(alpm_pkg_get_reason(lpkg), spkg, NULL);  						if(sync == NULL) { -							_alpm_pkg_free(dummy);  							pm_errno = PM_ERR_MEMORY; -							synclist_free(*syncpkgs); +							alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free); +							alpm_list_free(*syncpkgs); +							*syncpkgs = NULL;  							return(-1);  						} -						sync->data = alpm_list_add(NULL, dummy); +						sync->removes = alpm_list_add(NULL, lpkg);  						*syncpkgs = alpm_list_add(*syncpkgs, sync);  					}  					_alpm_log(PM_LOG_DEBUG, "%s-%s elected for removal (to be replaced by %s-%s)\n", @@ -180,6 +160,35 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,  	return(0);  } +/** Check for new version of pkg in sync repos + * (only the first occurrence is considered in sync) + */ +pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) +{ +	alpm_list_t *i; +	pmpkg_t *spkg = NULL; + +	for(i = dbs_sync; !spkg && i; i = i->next) { +		spkg = _alpm_db_get_pkgfromcache(i->data, alpm_pkg_get_name(pkg)); +	} + +	if(spkg == NULL) { +		_alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n", +				alpm_pkg_get_name(pkg)); +		return(NULL); +	} + +	/* compare versions and see if spkg is an upgrade */ +	if(_alpm_pkg_compare_versions(pkg, spkg)) { +		_alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", +					alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg), +					alpm_pkg_get_version(spkg)); +		return(spkg); +	} else { +		return(NULL); +	} +} +  /** Get a list of upgradable packages on the current system   * Adds out of date packages to *list.   * @arg list pointer to a list of pmsyncpkg_t. @@ -193,7 +202,7 @@ int SYMEXPORT alpm_sync_sysupgrade(pmdb_t *db_local,  int _alpm_sync_sysupgrade(pmtrans_t *trans,  		pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **syncpkgs)  { -	alpm_list_t *i, *j; +	alpm_list_t *i, *j, *replaced = NULL;  	ALPM_LOG_FUNC; @@ -205,76 +214,61 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans,  		return(-1);  	} -	/* match installed packages with the sync dbs and compare versions */ +	/* compute the to-be-replaced packages for efficiency */ +	for(i = *syncpkgs; i; i = i->next) { +		pmsyncpkg_t *sync = i->data; +		for(j = sync->removes; j; j = j->next) { +			replaced = alpm_list_add(replaced, j->data); +		} +	} + +	/* for all not-replaced local package we check for upgrade */  	_alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n");  	for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) { -		int replace = 0;  		pmpkg_t *local = i->data; -		pmpkg_t *spkg = NULL; -		pmsyncpkg_t *sync; - -		for(j = dbs_sync; !spkg && j; j = j->next) { -			spkg = _alpm_db_get_pkgfromcache(j->data, alpm_pkg_get_name(local)); -		} -		if(spkg == NULL) { -			_alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db -- skipping\n", -					alpm_pkg_get_name(local)); -			continue; -		} -		/* we don't care about a to-be-replaced package's newer version */ -		for(j = *syncpkgs; j && !replace; j=j->next) { -			sync = j->data; -			if(sync->type == PM_SYNC_TYPE_REPLACE) { -				if(_alpm_pkg_find(alpm_pkg_get_name(spkg), sync->data)) { -					replace = 1; -				} -			} -		} -		if(replace) { +		if(_alpm_pkg_find(alpm_pkg_get_name(local), replaced)) {  			_alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n",  					alpm_pkg_get_name(local));  			continue;  		} -		/* compare versions and see if we need to upgrade */ -		if(_alpm_pkg_compare_versions(local, spkg)) { -			_alpm_log(PM_LOG_DEBUG, "%s elected for upgrade (%s => %s)\n", -					alpm_pkg_get_name(local), alpm_pkg_get_version(local), -					alpm_pkg_get_version(spkg)); -			if(!_alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg))) { -				/* If package is in the ignorepkg list, skip it */ -				if(_alpm_pkg_should_ignore(spkg)) { -					_alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), -							alpm_pkg_get_name(local), alpm_pkg_get_version(local), -							alpm_pkg_get_version(spkg)); -					continue; -				} +		pmpkg_t *spkg = alpm_sync_newversion(local, dbs_sync); +		if(spkg) { +			/* we found a new version */ +			/* skip packages in IgnorePkg or in IgnoreGroup */ +			if(_alpm_pkg_should_ignore(spkg)) { +				_alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), +						alpm_pkg_get_name(local), alpm_pkg_get_version(local), +						alpm_pkg_get_version(spkg)); +				continue; +			} -				pmpkg_t *tmp = _alpm_pkg_dup(local); -				if(tmp == NULL) { -					pm_errno = PM_ERR_MEMORY; -					synclist_free(*syncpkgs); -					return(-1); -				} -				sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, tmp); -				if(sync == NULL) { -					_alpm_pkg_free(tmp); -					pm_errno = PM_ERR_MEMORY; -					synclist_free(*syncpkgs); -					return(-1); -				} -				*syncpkgs = alpm_list_add(*syncpkgs, sync); +			/* add the upgrade package to our pmsyncpkg_t list */ +			if(_alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg))) { +				/* avoid duplicated targets */ +				continue;  			} +			/* we can set any reason here, it will be overridden by add_commit */ +			pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_EXPLICIT, spkg, NULL); +			if(sync == NULL) { +				alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free); +				alpm_list_free(*syncpkgs); +				*syncpkgs = NULL; +				alpm_list_free(replaced); +				return(-1); +			} +			*syncpkgs = alpm_list_add(*syncpkgs, sync);  		}  	} +	alpm_list_free(replaced);  	return(0);  }  int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name)  { -	char targline[PKG_FULLNAME_LEN]; +	char *targline;  	char *targ;  	alpm_list_t *j;  	pmpkg_t *local; @@ -287,8 +281,8 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy  	ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));  	ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));  	ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); +	STRDUP(targline, name, RET_ERR(PM_ERR_MEMORY, -1)); -	strncpy(targline, name, PKG_FULLNAME_LEN);  	targ = strchr(targline, '/');  	if(targ) {  		/* we are looking for a package in a specific database */ @@ -301,13 +295,15 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy  				repo_found = 1;  				spkg = _alpm_db_get_pkgfromcache(db, targ);  				if(spkg == NULL) { -					RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); +					pm_errno = PM_ERR_PKG_NOT_FOUND; +					goto error;  				}  			}  		}  		if(!repo_found) {  			_alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline); -			RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1); +			pm_errno = PM_ERR_PKG_REPO_NOT_FOUND; +			goto error;  		}  	} else {  		targ = targline; @@ -316,10 +312,16 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy  			spkg = _alpm_db_get_pkgfromcache(db, targ);  		}  		if(spkg == NULL) { -			RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); +			pm_errno = PM_ERR_PKG_NOT_FOUND; +			goto error;  		}  	} +	if(_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) { +		FREE(targline); +		RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); +	} +  	if(_alpm_pkg_should_ignore(spkg)) {  		int resp;  		QUESTION(trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, spkg, NULL, NULL, &resp); @@ -346,41 +348,85 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy  	}  	/* add the package to the transaction */ -	if(!_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) { -		pmpkg_t *dummy = NULL; -		if(local) { -			dummy = _alpm_pkg_dup(local); -			if(dummy == NULL) { -				RET_ERR(PM_ERR_MEMORY, -1); -			} -		} -		sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, dummy); -		if(sync == NULL) { -			_alpm_pkg_free(dummy); -			RET_ERR(PM_ERR_MEMORY, -1); -		} -		_alpm_log(PM_LOG_DEBUG, "adding target '%s' to the transaction set\n", -							alpm_pkg_get_name(spkg)); -		trans->packages = alpm_list_add(trans->packages, sync); +	sync = _alpm_sync_new(PM_PKG_REASON_EXPLICIT, spkg, NULL); +	if(sync == NULL) { +		goto error;  	} +	_alpm_log(PM_LOG_DEBUG, "adding target '%s' to the transaction set\n", +						alpm_pkg_get_name(spkg)); +	trans->packages = alpm_list_add(trans->packages, sync); +	FREE(targline);  	return(0); + +error: +	if(targline) { +		FREE(targline); +	} +	return(-1);  }  /* Helper functions for alpm_list_remove - */ +*/  static int syncpkg_cmp(const void *s1, const void *s2)  {  	const pmsyncpkg_t *sp1 = s1;  	const pmsyncpkg_t *sp2 = s2;  	pmpkg_t *p1, *p2; -  p1 = alpm_sync_get_pkg(sp1); -  p2 = alpm_sync_get_pkg(sp2); +	p1 = alpm_sync_get_pkg(sp1); +	p2 = alpm_sync_get_pkg(sp2);  	return(strcmp(alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)));  } +/** Compute the size of the files that will be downloaded to install a + * package. + * @param newpkg the new package to upgrade to + */ +static int compute_download_size(pmpkg_t *newpkg) +{ +	const char *fname; +	char *fpath; +	unsigned long size = 0; + +	fname = alpm_pkg_get_filename(newpkg); +	ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); +	fpath = _alpm_filecache_find(fname); + +	if(fpath) { +		FREE(fpath); +		size = 0; +	} else if(handle->usedelta) { +		unsigned long dltsize; +		unsigned long pkgsize = alpm_pkg_get_size(newpkg); + +		dltsize = _alpm_shortest_delta_path( +			alpm_pkg_get_deltas(newpkg), +			alpm_pkg_get_filename(newpkg), +			alpm_pkg_get_md5sum(newpkg), +			&newpkg->delta_path); + +		if(newpkg->delta_path && (dltsize < pkgsize * MAX_DELTA_RATIO)) { +			_alpm_log(PM_LOG_DEBUG, "using delta size\n"); +			size = dltsize; +		} else { +			_alpm_log(PM_LOG_DEBUG, "using package size\n"); +			size = alpm_pkg_get_size(newpkg); +			alpm_list_free(newpkg->delta_path); +			newpkg->delta_path = NULL; +		} +	} else { +		size = alpm_pkg_get_size(newpkg); +	} + +	_alpm_log(PM_LOG_DEBUG, "setting download size %ld for pkg %s\n", size, +			alpm_pkg_get_name(newpkg)); + +	newpkg->download_size = size; +	return(0); +} +  int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data)  {  	alpm_list_t *deps = NULL; @@ -397,14 +443,15 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync  		*data = NULL;  	} -	if(!(trans->flags & PM_TRANS_FLAG_DEPENDSONLY)) { -		for(i = trans->packages; i; i = i->next) { -			pmsyncpkg_t *sync = i->data; -			list = alpm_list_add(list, sync->pkg); -		} +	for(i = trans->packages; i; i = i->next) { +		pmsyncpkg_t *sync = i->data; +		list = alpm_list_add(list, sync->pkg);  	}  	if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { +		/* store a pointer to the last original target so we can tell what was +		 * pulled by resolvedeps */ +		alpm_list_t *pulled = alpm_list_last(list);  		/* Resolve targets dependencies */  		EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL);  		_alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n"); @@ -412,10 +459,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync  		/* build remove list for resolvedeps */  		for(i = trans->packages; i; i = i->next) {  			pmsyncpkg_t *sync = i->data; -			if(sync->type == PM_SYNC_TYPE_REPLACE) { -				for(j = sync->data; j; j = j->next) { -					remove = alpm_list_add(remove, j->data); -				} +			for(j = sync->removes; j; j = j->next) { +				remove = alpm_list_add(remove, j->data);  			}  		} @@ -429,33 +474,27 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync  			}  		} -		if((trans->flags & PM_TRANS_FLAG_DEPENDSONLY)) { -			FREELIST(trans->packages); -		} - -		for(i = list; i; i = i->next) { -			/* add the dependencies found by resolvedeps to the transaction set */ +		for(i = pulled->next; i; i = i->next) {  			pmpkg_t *spkg = i->data; -			if(!_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) { -				pmsyncpkg_t *sync = _alpm_sync_new(PM_SYNC_TYPE_DEPEND, spkg, NULL); -				if(sync == NULL) { -					ret = -1; -					goto cleanup; -				} -				trans->packages = alpm_list_add(trans->packages, sync); -				_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", -									alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg)); +			pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_DEPEND, spkg, NULL); +			if(sync == NULL) { +				ret = -1; +				goto cleanup;  			} +			trans->packages = alpm_list_add(trans->packages, sync); +			_alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", +								alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg));  		}  		/* re-order w.r.t. dependencies */ -		alpm_list_t *sortlist = _alpm_sortbydeps(list, PM_TRANS_TYPE_ADD); +		alpm_list_t *sortlist = _alpm_sortbydeps(list, 0);  		alpm_list_t *newpkgs = NULL;  		for(i = sortlist; i; i = i->next) {  			for(j = trans->packages; j; j = j->next) {  				pmsyncpkg_t *s = j->data;  				if(s->pkg == i->data) {  					newpkgs = alpm_list_add(newpkgs, s); +					break;  				}  			}  		} @@ -472,180 +511,126 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync  		EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL);  		_alpm_log(PM_LOG_DEBUG, "looking for conflicts\n"); -		deps = _alpm_checkconflicts(db_local, list); -		if(deps) { -			int errorout = 0; -			alpm_list_t *asked = NULL; -			pmconflict_t *conflict = NULL; - -			for(i = deps; i && !errorout; i = i->next) { -				pmsyncpkg_t *sync; -				pmpkg_t *found = NULL; - -				conflict = i->data; -				_alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", -						conflict->package1, conflict->package2); -				/* check if the conflicting package is about to be removed/replaced. -				 * if so, then just ignore it. */ -				for(j = trans->packages; j && !found; j = j->next) { -					sync = j->data; -					if(sync->type == PM_SYNC_TYPE_REPLACE) { -						found = _alpm_pkg_find(conflict->package2, sync->data); -					} -				} -				if(found) { -					_alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n", -							alpm_pkg_get_name(found)); -					continue; -				} -				sync = _alpm_sync_find(trans->packages, conflict->package1); -				if(sync == NULL) { -					_alpm_log(PM_LOG_DEBUG, "'%s' not found in transaction set -- skipping\n", -					          conflict->package1); -					continue; -				} -				pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2); -				/* check if this package provides the package it's conflicting with */ -				if(alpm_list_find(alpm_pkg_get_provides(sync->pkg), -							conflict->package2, _alpm_prov_cmp)) { -					/* treat like a replaces item so requiredby fields are -					 * inherited properly. */ -					_alpm_log(PM_LOG_DEBUG, "package '%s' provides its own conflict\n", -							conflict->package1); -					if(!local) { -						char *rmpkg = NULL; -						void *target, *depend; -						/* hmmm, package2 isn't installed, so it must be conflicting -						 * with another package in our final list.  For example: -						 * -						 *     pacman -S blackbox xfree86 -						 * -						 * If no x-servers are installed and blackbox pulls in xorg, then -						 * xorg and xfree86 will conflict with each other.  In this case, -						 * we should follow the user's preference and rip xorg out of final, -						 * opting for xfree86 instead. -						 */ - -						/* figure out which one was requested in targets. If they both -						 * were, then it's still an unresolvable conflict. */ -						target = alpm_list_find_str(trans->targets, conflict->package1); -						depend = alpm_list_find_str(trans->targets, conflict->package2); -						if(depend && !target) { -							_alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n", -								conflict->package2); -							/* remove conflict->package1 */ -							rmpkg = conflict->package1; -						} else if(target && !depend) { -							_alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n", -								conflict->package1); -							/* remove conflict->package2 */ -							rmpkg = conflict->package2; -						} else { -							/* miss->target2 is not needed, miss->target already provides -							 * it, let's resolve the conflict */ -							rmpkg = conflict->package2; -						} -						if(rmpkg) { -							pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages, rmpkg); -							if(rsync) { -								void *vpkg; -								_alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n", -										rsync->pkg->name); -								trans->packages = alpm_list_remove(trans->packages, rsync, -										syncpkg_cmp, &vpkg); -								_alpm_sync_free(vpkg); -							} -							continue; -						} +		/* 1. check for conflicts in the target list */ +		_alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); +		deps = _alpm_innerconflicts(list); + +		for(i = deps; i; i = i->next) { +			pmconflict_t *conflict = i->data; +			pmsyncpkg_t *rsync, *sync, *sync1, *sync2; + +			/* have we already removed one of the conflicting targets? */ +			sync1 = _alpm_sync_find(trans->packages, conflict->package1); +			sync2 = _alpm_sync_find(trans->packages, conflict->package2); +			if(!sync1 || !sync2) { +				continue; +			} + +			_alpm_log(PM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n", +					conflict->package1, conflict->package2); + +			/* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ +			if(alpm_list_find(alpm_pkg_get_provides(sync1->pkg), +						conflict->package2, _alpm_prov_cmp)) { +				rsync = sync2; +				sync = sync1; +			} else if(alpm_list_find(alpm_pkg_get_provides(sync2->pkg), +						conflict->package1, _alpm_prov_cmp)) { +				rsync = sync1; +				sync = sync2; +			} else { +				_alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); +				pm_errno = PM_ERR_CONFLICTING_DEPS; +				ret = -1; +				if(data) { +					pmconflict_t *newconflict = _alpm_conflict_dup(conflict); +					if(newconflict) { +						*data = alpm_list_add(*data, newconflict);  					}  				} -				/* It's a conflict -- see if they want to remove it */ -				_alpm_log(PM_LOG_DEBUG, "resolving package '%s' conflict\n", -						conflict->package1); -				if(local) { -					int doremove = 0; -					if(!alpm_list_find_str(asked, conflict->package2)) { -						QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1, -								conflict->package2, NULL, &doremove); -						asked = alpm_list_add(asked, strdup(conflict->package2)); -						if(doremove) { -							pmpkg_t *q = _alpm_pkg_dup(local); -							if(sync->type != PM_SYNC_TYPE_REPLACE) { -								/* switch this sync type to REPLACE */ -								sync->type = PM_SYNC_TYPE_REPLACE; -								_alpm_pkg_free(sync->data); -								sync->data = NULL; -							} -							/* append to the replaces list */ -							_alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", -									conflict->package2); -							sync->data = alpm_list_add(sync->data, q); -							/* see if the package is in the current target list */ -							pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages, -									conflict->package2); -							if(rsync) { -								/* remove it from the target list */ -								void *vpkg; -								_alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n", -										conflict->package2); -								trans->packages = alpm_list_remove(trans->packages, rsync, -										syncpkg_cmp, &vpkg); -								_alpm_sync_free(vpkg); -							} -						} else { -							/* abort */ -							_alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); -							errorout = 1; -						} -					} -				} else { -					_alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); -					errorout = 1; +				alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); +				alpm_list_free(deps); +				goto cleanup; +			} + +			/* Prints warning */ +			_alpm_log(PM_LOG_WARNING, +					_("removing '%s' from target list because it conflicts with '%s'\n"), +					rsync->pkg->name, sync->pkg->name); +			void *vpkg; +			trans->packages = alpm_list_remove(trans->packages, rsync, +					syncpkg_cmp, &vpkg); +			pmsyncpkg_t *syncpkg = vpkg; +			list = alpm_list_remove(list, syncpkg->pkg, _alpm_pkg_cmp, NULL); +			_alpm_sync_free(syncpkg); +			continue; +		} + +		alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); +		alpm_list_free(deps); +		deps = NULL; + +		/* 2. we check for target vs db conflicts (and resolve)*/ +		_alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n"); +		deps = _alpm_outerconflicts(db_local, list); + +		for(i = deps; i; i = i->next) { +			pmconflict_t *conflict = i->data; + +			/* if conflict->package2 (the local package) is not elected for removal, +			   we ask the user */ +			int found = 0; +			for(j = trans->packages; j && !found; j = j->next) { +				pmsyncpkg_t *sync = j->data; +				if(_alpm_pkg_find(conflict->package2, sync->removes)) { +					found = 1;  				}  			} -			if(errorout) { -				/* The last conflict was unresolvable, so we duplicate it and add it to *data */ +			if(found) { +				continue; +			} + +			_alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", +					conflict->package1, conflict->package2); + +			pmsyncpkg_t *sync = _alpm_sync_find(trans->packages, conflict->package1); +			pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2); +			int doremove = 0; +			QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1, +								conflict->package2, NULL, &doremove); +			if(doremove) { +				/* append to the removes list */ +				_alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); +				sync->removes = alpm_list_add(sync->removes, local); +			} else { /* abort */ +				_alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));  				pm_errno = PM_ERR_CONFLICTING_DEPS; +				ret = -1;  				if(data) { -					pmconflict_t *lastconflict = conflict; -					if((conflict = malloc(sizeof(pmconflict_t))) == NULL) { -						_alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %zd bytes\n"), -								sizeof(pmconflict_t)); -						FREELIST(*data); -						pm_errno = PM_ERR_MEMORY; -					} else { -						*conflict = *lastconflict; -						*data = alpm_list_add(*data, conflict); +					pmconflict_t *newconflict = _alpm_conflict_dup(conflict); +					if(newconflict) { +						*data = alpm_list_add(*data, newconflict);  					}  				} -				FREELIST(asked); -				FREELIST(deps); -				ret = -1; +				alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); +				alpm_list_free(deps);  				goto cleanup;  			} -			FREELIST(asked); -			FREELIST(deps);  		}  		EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL); +		alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); +		alpm_list_free(deps);  	}  	if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { -		/* rebuild remove and list */ -		alpm_list_free(list); -		list = NULL; -		for(i = trans->packages; i; i = i->next) { -			pmsyncpkg_t *sync = i->data; -			list = alpm_list_add(list, sync->pkg); -		} +		/* rebuild remove list */  		alpm_list_free(remove);  		remove = NULL;  		for(i = trans->packages; i; i = i->next) {  			pmsyncpkg_t *sync = i->data; -			if(sync->type == PM_SYNC_TYPE_REPLACE) { -				for(j = sync->data; j; j = j->next) { -					remove = alpm_list_add(remove, j->data); -				} +			for(j = sync->removes; j; j = j->next) { +				remove = alpm_list_add(remove, j->data);  			}  		} @@ -657,11 +642,20 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync  			if(data) {  				*data = deps;  			} else { -				FREELIST(deps); +				alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); +				alpm_list_free(deps);  			}  			goto cleanup;  		}  	} +	for(i = list; i; i = i->next) { +		/* update download size field */ +		pmpkg_t *spkg = i->data; +		if(compute_download_size(spkg) != 0) { +			ret = -1; +			goto cleanup; +		} +	}  cleanup:  	alpm_list_free(list); @@ -670,86 +664,14 @@ cleanup:  	return(ret);  } -/** Returns a list of deltas that should be downloaded instead of the - * package. - * - * It first tests if a delta path exists between the currently installed - * version (if any) and the version to upgrade to. If so, the delta path - * is used if its size is below a set percentage (MAX_DELTA_RATIO) of - * the package size, Otherwise, an empty list is returned. - * - * @param newpkg the new package to upgrade to - * @param db_local the local database - * - * @return the list of pmdelta_t * objects. NULL (the empty list) is - * returned if the package should be downloaded instead of deltas. - */ -static alpm_list_t *pkg_upgrade_delta_path(pmpkg_t *newpkg, pmdb_t *db_local) -{ -	pmpkg_t *oldpkg = alpm_db_get_pkg(db_local, newpkg->name); -	alpm_list_t *ret = NULL; - -	if(oldpkg) { -		const char *oldname = alpm_pkg_get_filename(oldpkg); -		char *oldpath = _alpm_filecache_find(oldname); - -		if(oldpath) { -			alpm_list_t *deltas = _alpm_shortest_delta_path( -					alpm_pkg_get_deltas(newpkg), -					alpm_pkg_get_version(oldpkg), -					alpm_pkg_get_version(newpkg)); - -			if(deltas) { -				unsigned long dltsize = _alpm_delta_path_size(deltas); -				unsigned long pkgsize = alpm_pkg_get_size(newpkg); - -				if(dltsize < pkgsize * MAX_DELTA_RATIO) { -					ret = deltas; -				} else { -					ret = NULL; -					alpm_list_free(deltas); -				} -			} - -			FREE(oldpath); -		} -	} - -	return(ret); -} -  /** Returns the size of the files that will be downloaded to install a   * package. - *   * @param newpkg the new package to upgrade to - * @param db_local the local database - *   * @return the size of the download   */ -unsigned long SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg, pmdb_t *db_local) +unsigned long SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg)  { -	char *fpath = _alpm_filecache_find(alpm_pkg_get_filename(newpkg)); -	unsigned long size = 0; - -	if(fpath) { -		size = 0; -	} else if(handle->usedelta) { -		alpm_list_t *deltas = pkg_upgrade_delta_path(newpkg, db_local); - -		if(deltas) { -			size = _alpm_delta_path_size_uncached(deltas); -		} else { -			size = alpm_pkg_get_size(newpkg); -		} - -		alpm_list_free(deltas); -	} else { -		size = alpm_pkg_get_size(newpkg); -	} - -	FREE(fpath); - -	return(size); +	return(newpkg->download_size);  }  /** Applies delta files to create an upgraded package file. @@ -758,88 +680,82 @@ unsigned long SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg, pmdb_t *db_local   * ending package files.   *   * @param trans the transaction - * @param patches A list of alternating pmpkg_t * and pmdelta_t * - * objects. The patch command will be built using the pmpkg_t, pmdelta_t - * pair.   *   * @return 0 if all delta files were able to be applied, 1 otherwise.   */ -static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches) +static int apply_deltas(pmtrans_t *trans)  { -	/* keep track of the previous package in the loop to decide if a -	 * package file should be deleted */ -	pmpkg_t *lastpkg = NULL; -	int lastpkg_failed = 0; +	alpm_list_t *i;  	int ret = 0;  	const char *cachedir = _alpm_filecache_setup(); -	alpm_list_t *p = patches; -	while(p) { -		pmpkg_t *pkg; -		pmdelta_t *d; -		char command[PATH_MAX], fname[PATH_MAX]; -		char pkgfilename[PKG_FILENAME_LEN]; +	for(i = trans->packages; i; i = i->next) { +		pmsyncpkg_t *sync = i->data; +		pmpkg_t *spkg = sync->pkg; +		alpm_list_t *delta_path = spkg->delta_path; +		alpm_list_t *dlts = NULL; -		pkg = alpm_list_getdata(p); -		p = alpm_list_next(p); +		if(!delta_path) { +			continue; +		} -		d = alpm_list_getdata(p); -		p = alpm_list_next(p); +		for(dlts = delta_path; dlts; dlts = dlts->next) { +			pmdelta_t *d = dlts->data; +			char *delta, *from, *to; +			char command[PATH_MAX]; +			int len = 0; -		/* if patching fails, ignore the rest of that package's deltas */ -		if(lastpkg_failed) { -			if(pkg == lastpkg) { -				continue; +			delta = _alpm_filecache_find(d->delta); +			/* the initial package might be in a different cachedir */ +			if(dlts == delta_path) { +				from = _alpm_filecache_find(d->from);  			} else { -				lastpkg_failed = 0; +				/* len = cachedir len + from len + '/' + null */ +				len = strlen(cachedir) + strlen(d->from) + 2; +				CALLOC(from, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1)); +				snprintf(from, len, "%s/%s", cachedir, d->from);  			} -		} +			len = strlen(cachedir) + strlen(d->to) + 2; +			CALLOC(to, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1)); +			snprintf(to, len, "%s/%s", cachedir, d->to); -		/* an example of the patch command: (using /cache for cachedir) -		 * xdelta patch /cache/pacman_3.0.0-1_to_3.0.1-1-i686.delta \ -		 *              /cache/pacman-3.0.0-1-i686.pkg.tar.gz       \ -		 *              /cache/pacman-3.0.1-1-i686.pkg.tar.gz -		 */ - -		/* build the patch command */ -		snprintf(command, PATH_MAX, -				"xdelta patch"         /* the command */ -				" %s/%s"               /* the delta */ -				" %s/%s-%s-%s" PKGEXT  /* the 'from' package */ -				" %s/%s-%s-%s" PKGEXT, /* the 'to' package */ -				cachedir, d->filename, -				cachedir, pkg->name, d->from, pkg->arch, -				cachedir, pkg->name, d->to, pkg->arch); - -		_alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command); - -		snprintf(pkgfilename, PKG_FILENAME_LEN, "%s-%s-%s" PKGEXT, -				pkg->name, d->to, pkg->arch); - -		EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, pkgfilename, d->filename); - -		if(system(command) == 0) { -			EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_DONE, NULL, NULL); - -			/* delete the delta file */ -			snprintf(fname, PATH_MAX, "%s/%s", cachedir, d->filename); -			unlink(fname); - -			/* Delete the 'from' package but only if it is an intermediate -			 * package. The starting 'from' package should be kept, just -			 * as if deltas were not used. Delete the package file if the -			 * previous iteration of the loop used the same package. */ -			if(pkg == lastpkg) { -				snprintf(fname, PATH_MAX, "%s/%s-%s-%s" PKGEXT, -						cachedir, pkg->name, d->from, pkg->arch); -				unlink(fname); -			} else { -				lastpkg = pkg; +			/* an example of the patch command: (using /cache for cachedir) +			 * xdelta patch /path/to/pacman_3.0.0-1_to_3.0.1-1-i686.delta \ +			 *              /path/to/pacman-3.0.0-1-i686.pkg.tar.gz       \ +			 *              /cache/pacman-3.0.1-1-i686.pkg.tar.gz +			 */ + +			/* build the patch command */ +			snprintf(command, PATH_MAX, "xdelta patch %s %s %s", delta, from, to); + +			_alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command); + +			EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, d->to, d->delta); + +			int retval = system(command); +			if(retval == 0) { +				EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_DONE, NULL, NULL); + +				/* delete the delta file */ +				unlink(delta); + +				/* Delete the 'from' package but only if it is an intermediate +				 * package. The starting 'from' package should be kept, just +				 * as if deltas were not used. */ +				if(dlts != delta_path) { +					unlink(from); +				} +			} +			FREE(from); +			FREE(to); +			FREE(delta); + +			if(retval != 0) { +				/* one delta failed for this package, cancel the remaining ones */ +				EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL); +				ret = 1; +				break;  			} -		} else { -			EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL); -			lastpkg_failed = 1; -			ret = 1;  		}  	} @@ -854,107 +770,29 @@ static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches)   * @param trans the transaction   * @param filename the filename of the file to test   * @param md5sum the expected md5sum of the file - * @param data data to write the error messages to   * - * @return 0 if the md5sum matched, 1 otherwise + * @return 0 if the md5sum matched, 1 if not, -1 in case of errors   */  static int test_md5sum(pmtrans_t *trans, const char *filename, -		const char *md5sum, alpm_list_t **data) +		const char *md5sum)  {  	char *filepath; -	char *md5sum2; -	char *errormsg = NULL; -	int ret = 0; +	int ret;  	filepath = _alpm_filecache_find(filename); -	md5sum2 = alpm_get_md5sum(filepath); -	if(md5sum == NULL) { -		if(data) { -			/* TODO wtf is this? malloc'd strings for error messages? */ -			if((errormsg = calloc(512, sizeof(char))) == NULL) { -				RET_ERR(PM_ERR_MEMORY, -1); -			} -			snprintf(errormsg, 512, _("can't get md5 checksum for file %s\n"), -					filename); -			*data = alpm_list_add(*data, errormsg); -		} -		ret = 1; -	} else if(md5sum2 == NULL) { -		if(data) { -			if((errormsg = calloc(512, sizeof(char))) == NULL) { -				RET_ERR(PM_ERR_MEMORY, -1); -			} -			snprintf(errormsg, 512, _("can't get md5 checksum for file %s\n"), -					filename); -			*data = alpm_list_add(*data, errormsg); -		} -		ret = 1; -	} else if(strcmp(md5sum, md5sum2) != 0) { +	ret = _alpm_test_md5sum(filepath, md5sum); + +	if(ret == 1) {  		int doremove = 0;  		QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)filename,  				NULL, NULL, &doremove);  		if(doremove) {  			unlink(filepath);  		} -		if(data) { -			if((errormsg = calloc(512, sizeof(char))) == NULL) { -				RET_ERR(PM_ERR_MEMORY, -1); -			} -			snprintf(errormsg, 512, _("file %s was corrupted (bad MD5 checksum)\n"), -					filename); -			*data = alpm_list_add(*data, errormsg); -		} -		ret = 1;  	}  	FREE(filepath); -	FREE(md5sum2); - -	return(ret); -} - -/** Compares the md5sum of a delta to the expected value. - * - * @param trans the transaction - * @param delta the delta to test - * @param data data to write the error messages to - * - * @return 0 if the md5sum matched, 1 otherwise - */ -static int test_delta_md5sum(pmtrans_t *trans, pmdelta_t *delta, -		alpm_list_t **data) -{ -	const char *filename; -	const char *md5sum; -	int ret = 0; - -	filename = alpm_delta_get_filename(delta); -	md5sum = alpm_delta_get_md5sum(delta); - -	ret = test_md5sum(trans, filename, md5sum, data); - -	return(ret); -} - -/** Compares the md5sum of a package to the expected value. - * - * @param trans the transaction - * @param pkg the package to test - * @param data data to write the error messages to - * - * @return 0 if the md5sum matched, 1 otherwise - */ -static int test_pkg_md5sum(pmtrans_t *trans, pmpkg_t *pkg, alpm_list_t **data) -{ -	const char *filename; -	const char *md5sum; -	int ret = 0; - -	filename = alpm_pkg_get_filename(pkg); -	md5sum = alpm_pkg_get_md5sum(pkg); - -	ret = test_md5sum(trans, filename, md5sum, data);  	return(ret);  } @@ -962,11 +800,12 @@ static int test_pkg_md5sum(pmtrans_t *trans, pmpkg_t *pkg, alpm_list_t **data)  int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  {  	alpm_list_t *i, *j, *files = NULL; -	alpm_list_t *patches = NULL, *deltas = NULL; +	alpm_list_t *deltas = NULL;  	pmtrans_t *tr = NULL; -	int replaces = 0, retval = 0; +	int replaces = 0; +	int errors = 0;  	const char *cachedir = NULL; -	int dltotal = 0, dl = 0; +	int ret = -1;  	ALPM_LOG_FUNC; @@ -976,14 +815,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  	cachedir = _alpm_filecache_setup();  	trans->state = STATE_DOWNLOADING; -	/* Sum up the download sizes. This has to be in its own loop because -	 * the download loop is grouped by db. */ -	for(j = trans->packages; j; j = j->next) { -		pmsyncpkg_t *sync = j->data; -		pmpkg_t *spkg = sync->pkg; -		dltotal += alpm_pkg_download_size(spkg, db_local); -	} -  	/* group sync records by repository and download */  	for(i = handle->dbs_sync; i; i = i->next) {  		pmdb_t *current = i->data; @@ -997,60 +828,45 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  				const char *fname = NULL;  				fname = alpm_pkg_get_filename(spkg); +				ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1));  				if(trans->flags & PM_TRANS_FLAG_PRINTURIS) {  					EVENT(trans, PM_TRANS_EVT_PRINTURI, (char *)alpm_db_get_url(current),  							(char *)fname);  				} else { -					char *fpath = _alpm_filecache_find(fname); -					if(!fpath) { -						if(handle->usedelta) { -							alpm_list_t *delta_path = pkg_upgrade_delta_path(spkg, db_local); - -							if(delta_path) { -								alpm_list_t *dlts = NULL; - -								for(dlts = delta_path; dlts; dlts = alpm_list_next(dlts)) { -									pmdelta_t *d = (pmdelta_t *)alpm_list_getdata(dlts); -									char *fpath2 = _alpm_filecache_find(d->filename); - -									if(!fpath2) { -										/* add the delta filename to the download list if -										 * it's not in the cache*/ -										files = alpm_list_add(files, strdup(d->filename)); -									} - -									/* save the package and delta so that the xdelta patch -									 * command can be run after the downloads finish */ -									patches = alpm_list_add(patches, spkg); -									patches = alpm_list_add(patches, d); - -									/* keep a list of the delta files for md5sums */ -									deltas = alpm_list_add(deltas, d); +					if(spkg->download_size != 0) { +						alpm_list_t *delta_path = spkg->delta_path; +						if(delta_path) { +							alpm_list_t *dlts = NULL; + +							for(dlts = delta_path; dlts; dlts = dlts->next) { +								pmdelta_t *d = dlts->data; + +								if(d->download_size != 0) { +									/* add the delta filename to the download list if +									 * it's not in the cache */ +									files = alpm_list_add(files, strdup(d->delta));  								} -								alpm_list_free(delta_path); -								delta_path = NULL; -							} else { -								/* no deltas to download, so add the file to the -								 * download list */ -								files = alpm_list_add(files, strdup(fname)); +								/* keep a list of the delta files for md5sums */ +								deltas = alpm_list_add(deltas, d);  							} +  						} else {  							/* not using deltas, so add the file to the download list */  							files = alpm_list_add(files, strdup(fname));  						}  					} -					FREE(fpath);  				}  			}  		}  		if(files) {  			EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); -			if(_alpm_downloadfiles(current->servers, cachedir, files, &dl, dltotal)) { +			if(_alpm_download_files(files, current->servers, cachedir)) {  				_alpm_log(PM_LOG_WARNING, _("failed to retrieve some files from %s\n"),  						current->treename); -				RET_ERR(PM_ERR_RETRIEVE, -1); +				pm_errno = PM_ERR_RETRIEVE; +				goto error;  			}  			FREELIST(files);  		} @@ -1064,35 +880,31 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  		/* only output if there are deltas to work with */  		if(deltas) { +			errors = 0;  			/* Check integrity of deltas */  			EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL);  			for(i = deltas; i; i = i->next) {  				pmdelta_t *d = alpm_list_getdata(i); +				const char *filename = alpm_delta_get_filename(d); +				const char *md5sum = alpm_delta_get_md5sum(d); -				ret = test_delta_md5sum(trans, d, data); - -				if(ret == 1) { -					retval = 1; -				} else if(ret == -1) { /* -1 is for serious errors */ -					RET_ERR(pm_errno, -1); +				if(test_md5sum(trans, filename, md5sum) != 0) { +					errors++; +					*data = alpm_list_add(*data, strdup(filename));  				}  			} -			if(retval) { -				pm_errno = PM_ERR_DLT_CORRUPTED; +			if(errors) { +				pm_errno = PM_ERR_DLT_INVALID;  				goto error;  			}  			EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL);  			/* Use the deltas to generate the packages */  			EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL); -			ret = apply_deltas(trans, patches); +			ret = apply_deltas(trans);  			EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL); -			alpm_list_free(patches); -			patches = NULL; -			alpm_list_free(deltas); -			deltas = NULL;  		}  		if(ret) {  			pm_errno = PM_ERR_DLT_PATCHFAILED; @@ -1103,21 +915,20 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  	/* Check integrity of packages */  	EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL); +	errors = 0;  	for(i = trans->packages; i; i = i->next) {  		pmsyncpkg_t *sync = i->data;  		pmpkg_t *spkg = sync->pkg; -		int ret = 0; +		const char *filename = alpm_pkg_get_filename(spkg); +		const char *md5sum = alpm_pkg_get_md5sum(spkg); -		ret = test_pkg_md5sum(trans, spkg, data); - -		if(ret == 1) { -			retval = 1; -		} else if(ret == -1) { /* -1 is for serious errors */ -			RET_ERR(pm_errno, -1); +		if(test_md5sum(trans, filename, md5sum) != 0) { +			errors++; +			*data = alpm_list_add(*data, strdup(filename));  		}  	} -	if(retval) { -		pm_errno = PM_ERR_PKG_CORRUPTED; +	if(errors) { +		pm_errno = PM_ERR_PKG_INVALID;  		goto error;  	}  	EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); @@ -1130,7 +941,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  	tr = _alpm_trans_new();  	if(tr == NULL) {  		_alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n")); -		pm_errno = PM_ERR_MEMORY;  		goto error;  	} @@ -1141,16 +951,14 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  	for(i = trans->packages; i; i = i->next) {  		pmsyncpkg_t *sync = i->data; -		if(sync->type == PM_SYNC_TYPE_REPLACE) { -			alpm_list_t *j; -			for(j = sync->data; j; j = j->next) { -				pmpkg_t *pkg = j->data; -				if(!_alpm_pkg_find(pkg->name, tr->packages)) { -					if(_alpm_trans_addtarget(tr, pkg->name) == -1) { -						goto error; -					} -					replaces++; +		alpm_list_t *j; +		for(j = sync->removes; j; j = j->next) { +			pmpkg_t *pkg = j->data; +			if(!_alpm_pkg_find(pkg->name, tr->packages)) { +				if(_alpm_trans_addtarget(tr, pkg->name) == -1) { +					goto error;  				} +				replaces++;  			}  		}  	} @@ -1175,7 +983,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  	tr = _alpm_trans_new();  	if(tr == NULL) {  		_alpm_log(PM_LOG_ERROR, _("could not create transaction\n")); -		pm_errno = PM_ERR_MEMORY;  		goto error;  	}  	if(_alpm_trans_init(tr, PM_TRANS_TYPE_UPGRADE, trans->flags | PM_TRANS_FLAG_NODEPS, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) { @@ -1189,6 +996,9 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  		char *fpath;  		fname = alpm_pkg_get_filename(spkg); +		if(fname == NULL) { +			goto error; +		}  		/* Loop through the cache dirs until we find a matching file */  		fpath = _alpm_filecache_find(fname); @@ -1201,9 +1011,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  		/* using alpm_list_last() is ok because addtarget() adds the new target at the  		 * end of the tr->packages list */  		spkg = alpm_list_last(tr->packages)->data; -		if(sync->type == PM_SYNC_TYPE_DEPEND) { -			spkg->reason = PM_PKG_REASON_DEPEND; -		} +		spkg->reason = sync->newreason;  	}  	if(_alpm_trans_prepare(tr, data) == -1) {  		_alpm_log(PM_LOG_ERROR, _("could not prepare transaction\n")); @@ -1214,15 +1022,15 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)  		_alpm_log(PM_LOG_ERROR, _("could not commit transaction\n"));  		goto error;  	} -	_alpm_trans_free(tr); -	tr = NULL; - -	return(0); +	ret = 0;  error: +	FREELIST(files); +	alpm_list_free(deltas); +	deltas = NULL;  	_alpm_trans_free(tr);  	tr = NULL; -	return(-1); +	return(ret);  }  pmsyncpkg_t *_alpm_sync_find(alpm_list_t *syncpkgs, const char* pkgname) @@ -1246,14 +1054,6 @@ pmsyncpkg_t *_alpm_sync_find(alpm_list_t *syncpkgs, const char* pkgname)  	return(NULL); /* not found */  } -pmsynctype_t SYMEXPORT alpm_sync_get_type(const pmsyncpkg_t *sync) -{ -	/* Sanity checks */ -	ASSERT(sync != NULL, return(-1)); - -	return sync->type; -} -  pmpkg_t SYMEXPORT *alpm_sync_get_pkg(const pmsyncpkg_t *sync)  {  	/* Sanity checks */ @@ -1262,12 +1062,12 @@ pmpkg_t SYMEXPORT *alpm_sync_get_pkg(const pmsyncpkg_t *sync)  	return sync->pkg;  } -void SYMEXPORT *alpm_sync_get_data(const pmsyncpkg_t *sync) +alpm_list_t SYMEXPORT *alpm_sync_get_removes(const pmsyncpkg_t *sync)  {  	/* Sanity checks */  	ASSERT(sync != NULL, return(NULL)); -	return sync->data; +	return sync->removes;  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index a6a3e74f..b71f0ef2 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -25,12 +25,12 @@  /* Sync package */  struct __pmsyncpkg_t { -	pmsynctype_t type; +	pmpkgreason_t newreason;  	pmpkg_t *pkg; -	void *data; +	alpm_list_t *removes;  }; -pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data); +pmsyncpkg_t *_alpm_sync_new(pmpkgreason_t newreason, pmpkg_t *spkg, alpm_list_t *removes);  void _alpm_sync_free(pmsyncpkg_t *data);  int _alpm_sync_sysupgrade(pmtrans_t *trans, diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index ecc40a0f..eb53e952 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -35,7 +35,6 @@  /* libalpm */  #include "trans.h"  #include "alpm_list.h" -#include "error.h"  #include "package.h"  #include "util.h"  #include "log.h" @@ -228,7 +227,6 @@ pmtrans_t *_alpm_trans_new()  	CALLOC(trans, 1, sizeof(pmtrans_t), RET_ERR(PM_ERR_MEMORY, NULL)); -	trans->targets = NULL;  	trans->packages = NULL;  	trans->skip_add = NULL;  	trans->skip_remove = NULL; @@ -250,10 +248,10 @@ void _alpm_trans_free(pmtrans_t *trans)  		return;  	} -	FREELIST(trans->targets);  	if(trans->type == PM_TRANS_TYPE_SYNC) {  		alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_sync_free); -	} else { +	} else if (trans->type == PM_TRANS_TYPE_REMOVE || +			trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {  		alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free);  	}  	alpm_list_free(trans->packages); @@ -307,13 +305,7 @@ int _alpm_trans_addtarget(pmtrans_t *trans, char *target)  	ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));  	ASSERT(target != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); -	if(alpm_list_find_str(trans->targets, target)) { -		return(0); -		//RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); -	} -  	switch(trans->type) { -		case PM_TRANS_TYPE_ADD:  		case PM_TRANS_TYPE_UPGRADE:  			if(_alpm_add_loadtarget(trans, handle->db_local, target) == -1) {  				/* pm_errno is set by _alpm_add_loadtarget() */ @@ -335,8 +327,6 @@ int _alpm_trans_addtarget(pmtrans_t *trans, char *target)  		break;  	} -	trans->targets = alpm_list_add(trans->targets, strdup(target)); -  	return(0);  } @@ -357,7 +347,6 @@ int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data)  	}  	switch(trans->type) { -		case PM_TRANS_TYPE_ADD:  		case PM_TRANS_TYPE_UPGRADE:  			if(_alpm_add_prepare(trans, handle->db_local, data) == -1) {  				/* pm_errno is set by _alpm_add_prepare() */ @@ -402,7 +391,6 @@ int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data)  	trans->state = STATE_COMMITING;  	switch(trans->type) { -		case PM_TRANS_TYPE_ADD:  		case PM_TRANS_TYPE_UPGRADE:  			if(_alpm_add_commit(trans, handle->db_local) == -1) {  				/* pm_errno is set by _alpm_add_commit() */ @@ -636,15 +624,6 @@ unsigned int SYMEXPORT alpm_trans_get_flags()  	return handle->trans->flags;  } -alpm_list_t SYMEXPORT * alpm_trans_get_targets() -{ -	/* Sanity checks */ -	ASSERT(handle != NULL, return(NULL)); -	ASSERT(handle->trans != NULL, return(NULL)); - -	return handle->trans->targets; -} -  alpm_list_t SYMEXPORT * alpm_trans_get_pkgs()  {  	/* Sanity checks */ diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 75608ce4..d74c3e90 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -39,7 +39,6 @@ struct __pmtrans_t {  	pmtranstype_t type;  	pmtransflag_t flags;  	pmtransstate_t state; -	alpm_list_t *targets;       /* list of (char *) */  	alpm_list_t *packages;      /* list of (pmpkg_t *) or (pmsyncpkg_t *) */  	alpm_list_t *skip_add;      /* list of (char *) */  	alpm_list_t *skip_remove;   /* list of (char *) */ diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index e1413a25..92e99914 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -43,7 +43,6 @@  /* libalpm */  #include "util.h"  #include "log.h" -#include "error.h"  #include "package.h"  #include "alpm.h"  #include "alpm_list.h" @@ -216,27 +215,31 @@ int _alpm_makepath_mode(const char *path, mode_t mode)  	return(0);  } +#define CPBUFSIZE 8 * 1024 +  int _alpm_copyfile(const char *src, const char *dest)  {  	FILE *in, *out;  	size_t len; -	char buf[4097]; +	char *buf; +	int ret = 0; -	in = fopen(src, "r"); +	in = fopen(src, "rb");  	if(in == NULL) {  		return(1);  	} -	out = fopen(dest, "w"); +	out = fopen(dest, "wb");  	if(out == NULL) {  		fclose(in);  		return(1);  	} +	CALLOC(buf, 1, CPBUFSIZE, ret = 1; goto cleanup;); +  	/* do the actual file copy */ -	while((len = fread(buf, 1, 4096, in))) { +	while((len = fread(buf, 1, CPBUFSIZE, in))) {  		fwrite(buf, 1, len, out);  	} -	fclose(in);  	/* chmod dest to permissions of src, as long as it is not a symlink */  	struct stat statbuf; @@ -246,12 +249,14 @@ int _alpm_copyfile(const char *src, const char *dest)  		}  	} else {  		/* stat was unsuccessful */ -		fclose(out); -		return(1); +		ret = 1;  	} +cleanup: +	fclose(in);  	fclose(out); -	return(0); +	FREE(buf); +	return(ret);  }  /* Trim whitespace and newlines from a string @@ -371,6 +376,13 @@ int _alpm_lckrm()  /* Compression functions */ +/** + * @brief Unpack a specific file or all files in an archive. + * + * @param archive  the archive to unpack + * @param prefix   where to extract the files + * @param fn       a file within the archive to unpack or NULL for all + */  int _alpm_unpack(const char *archive, const char *prefix, const char *fn)  {  	int ret = 1; @@ -382,7 +394,7 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)  	ALPM_LOG_FUNC;  	if((_archive = archive_read_new()) == NULL) -		RET_ERR(PM_ERR_LIBARCHIVE_ERROR, -1); +		RET_ERR(PM_ERR_LIBARCHIVE, -1);  	archive_read_support_compression_all(_archive);  	archive_read_support_format_all(_archive); @@ -408,13 +420,17 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)  			archive_entry_set_mode(entry, 0755);  		} +		/* If a specific file was requested skip entries that don't match. */  		if (fn && strcmp(fn, entryname)) { +			_alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname);  			if (archive_read_data_skip(_archive) != ARCHIVE_OK) {  				ret = 1;  				goto cleanup;  			}  			continue;  		} + +		/* Extract the archive entry. */  		ret = 0;  		snprintf(expath, PATH_MAX, "%s/%s", prefix, entryname);  		archive_entry_set_pathname(entry, expath); @@ -535,8 +551,8 @@ int _alpm_str_cmp(const void *s1, const void *s2)  	return(strcmp(s1, s2));  } -/** Find a package file in an alpm cachedir. - * @param filename name of package file to find +/** Find a filename in a registered alpm cachedir. + * @param filename name of file to find   * @return malloced path of file, NULL if not found   */  char *_alpm_filecache_find(const char* filename) @@ -640,13 +656,7 @@ char SYMEXPORT *alpm_get_md5sum(const char *filename)  	ret = md5_file(filename, output);  	if (ret > 0) { -		if (ret == 1) { -			_alpm_log(PM_LOG_ERROR, _("md5: %s can't be opened\n"), filename); -		} else if (ret == 2) { -			_alpm_log(PM_LOG_ERROR, _("md5: %s can't be read\n"), filename); -		} - -		return(NULL); +		RET_ERR(PM_ERR_NOT_A_FILE, NULL);  	}  	/* Convert the result to something readable */ @@ -660,4 +670,52 @@ char SYMEXPORT *alpm_get_md5sum(const char *filename)  	return(md5sum);  } +int _alpm_test_md5sum(const char *filepath, const char *md5sum) +{ +	char *md5sum2; +	int ret; + +	md5sum2 = alpm_get_md5sum(filepath); + +	if(md5sum == NULL || md5sum2 == NULL) { +		ret = -1; +	} else if(strcmp(md5sum, md5sum2) != 0) { +		ret = 1; +	} else { +		ret = 0; +	} + +	FREE(md5sum2); +	return(ret); +} + +char *_alpm_archive_fgets(char *line, size_t size, struct archive *a) +{ +	/* for now, just read one char at a time until we get to a +	 * '\n' char. we can optimize this later with an internal +	 * buffer. */ +	/* leave room for zero terminator */ +	char *last = line + size - 1; +	char *i; + +	for(i = line; i < last; i++) { +		int ret = archive_read_data(a, i, 1); +		/* special check for first read- if null, return null, +		 * this indicates EOF */ +		if(i == line && (ret <= 0 || *i == '\0')) { +			return(NULL); +		} +		/* check if read value was null or newline */ +		if(ret <= 0 || *i == '\0' || *i == '\n') { +			last = i + 1; +			break; +		} +	} + +	/* always null terminate the buffer */ +	*last = '\0'; + +	return(line); +} +  /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index e9e0af1f..6c7a05e9 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -30,6 +30,7 @@  #include <stdarg.h>  #include <time.h>  #include <sys/stat.h> /* struct stat */ +#include <archive.h> /* struct archive */  #ifdef ENABLE_NLS  #include <libintl.h> /* here so it doesn't need to be included elsewhere */ @@ -43,12 +44,17 @@  #define MALLOC(p, s, action) do { p = calloc(1, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0)  #define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0) -#define STRDUP(r, s, action) do { r = strdup(s); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } while(0) +/* This strdup macro is NULL safe- copying NULL will yield NULL */ +#define STRDUP(r, s, action) do { if(s != NULL) { r = strdup(s); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } else { r = NULL; } } while(0) -#define FREE(p) do { if(p) { free(p); p = NULL; } } while(0) +#define FREE(p) do { free(p); p = NULL; } while(0)  #define ASSERT(cond, action) do { if(!(cond)) { action; } } while(0) +#define RET_ERR(err, ret) do { pm_errno = (err); \ +	_alpm_log(PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerrorlast()); \ +	return(ret); } while(0) +  int _alpm_makepath(const char *path);  int _alpm_makepath_mode(const char *path, mode_t mode);  int _alpm_copyfile(const char *src, const char *dest); @@ -64,6 +70,8 @@ int _alpm_str_cmp(const void *s1, const void *s2);  char *_alpm_filecache_find(const char *filename);  const char *_alpm_filecache_setup(void);  int _alpm_lstat(const char *path, struct stat *buf); +int _alpm_test_md5sum(const char *filepath, const char *md5sum); +char *_alpm_archive_fgets(char *line, size_t size, struct archive *a);  #ifndef HAVE_STRVERSCMP  int strverscmp(const char *, const char *); @@ -2,7 +2,7 @@  # NOTE: Changing this file will not affect anything until you rerun configure.  #  # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007  Free Software Foundation, Inc. +# 2007, 2008  Free Software Foundation, Inc.  # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996  #  # This program is free software; you can redistribute it and/or modify @@ -43,8 +43,8 @@ EXIT_FAILURE=1  PROGRAM=ltmain.sh  PACKAGE=libtool -VERSION=1.5.24 -TIMESTAMP=" (1.1220.2.455 2007/06/24 02:13:29)" +VERSION=1.5.26 +TIMESTAMP=" (1.1220.2.492 2008/01/30 06:40:56)"  # Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).  if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then @@ -113,15 +113,21 @@ esac  # These must not be set unconditionally because not all systems understand  # e.g. LANG=C (notably SCO).  # We save the old values to restore during execute mode. -for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +lt_env= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES  do    eval "if test \"\${$lt_var+set}\" = set; then  	  save_$lt_var=\$$lt_var +	  lt_env=\"$lt_var=\$$lt_var \$lt_env\"  	  $lt_var=C  	  export $lt_var  	fi"  done +if test -n "$lt_env"; then +  lt_env="env $lt_env" +fi +  # Make sure IFS has a sensible default  lt_nl='  ' @@ -485,7 +491,7 @@ do      echo "\  $PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP -Copyright (C) 2007  Free Software Foundation, Inc. +Copyright (C) 2008  Free Software Foundation, Inc.  This is free software; see the source for copying conditions.  There is NO  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."      exit $? @@ -788,6 +794,7 @@ if test -z "$show_help"; then      *.for) xform=for ;;      *.java) xform=java ;;      *.obj) xform=obj ;; +    *.sx) xform=sx ;;      esac      libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` @@ -956,7 +963,7 @@ EOF        $run $rm "$lobj" "$output_obj"        $show "$command" -      if $run eval "$command"; then : +      if $run eval $lt_env "$command"; then :        else  	test -n "$output_obj" && $run $rm $removelist  	exit $EXIT_FAILURE @@ -1028,7 +1035,7 @@ EOF        command="$command$suppress_output"        $run $rm "$obj" "$output_obj"        $show "$command" -      if $run eval "$command"; then : +      if $run eval $lt_env "$command"; then :        else  	$run $rm $removelist  	exit $EXIT_FAILURE @@ -1161,6 +1168,7 @@ EOF      thread_safe=no      vinfo=      vinfo_number=no +    single_module="${wl}-single_module"      func_infer_tag $base_compile @@ -1646,6 +1654,11 @@ EOF  	continue  	;; +      -multi_module) +	single_module="${wl}-multi_module" +	continue +	;; +        -module)  	module=yes  	continue @@ -2149,7 +2162,12 @@ EOF  	    continue  	  fi  	  name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` -	  for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do +	  if test "$linkmode" = lib; then +	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" +	  else +	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" +	  fi +	  for searchdir in $searchdirs; do  	    for search_ext in .la $std_shrext .so .a; do  	      # Search the libtool library  	      lib="$searchdir/lib${name}${search_ext}" @@ -2945,12 +2963,18 @@ EOF  		  # we do not want to link against static libs,  		  # but need to link against shared  		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` +		  eval deplibdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`  		  if test -n "$deplibrary_names" ; then  		    for tmp in $deplibrary_names ; do  		      depdepl=$tmp  		    done -		    if test -f "$path/$depdepl" ; then +		    if test -f "$deplibdir/$depdepl" ; then +		      depdepl="$deplibdir/$depdepl" +		    elif test -f "$path/$depdepl" ; then  		      depdepl="$path/$depdepl" +		    else +		      # Can't find it, oh well... +		      depdepl=  		    fi  		    # do not add paths which are already there  		    case " $newlib_search_path " in @@ -3098,9 +3122,10 @@ EOF      case $linkmode in      oldlib) -      if test -n "$deplibs"; then -	$echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 -      fi +      case " $deplibs" in +      *\ -l* | *\ -L*) +	$echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 ;; +      esac        if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then  	$echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 @@ -4237,9 +4262,10 @@ EOF        ;;      obj) -      if test -n "$deplibs"; then -	$echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 -      fi +      case " $deplibs" in +      *\ -l* | *\ -L*) +	$echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 ;; +      esac        if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then  	$echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 @@ -6478,7 +6504,7 @@ relink_command=\"$relink_command\""        fi        # Restore saved environment variables -      for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES        do  	eval "if test \"\${save_$lt_var+set}\" = set; then  		$lt_var=\$save_$lt_var; export $lt_var diff --git a/pactest/Makefile.am b/pactest/Makefile.am index 879f23d0..85bb8017 100644 --- a/pactest/Makefile.am +++ b/pactest/Makefile.am @@ -7,8 +7,7 @@ check_SCRIPTS = \  	pmrule.py \  	pmtest.py \  	util.py \ -	$(wildcard tests/*.py) \ -	tests/TESTS +	$(wildcard tests/*.py)  noinst_SCRIPTS = $(check_SCRIPTS) diff --git a/pactest/pmtest.py b/pactest/pmtest.py index cd532dcf..c4e6ffa0 100755 --- a/pactest/pmtest.py +++ b/pactest/pmtest.py @@ -199,7 +199,7 @@ class pmtest:          if pacman["gdb"]:              cmd.append("libtool gdb --args")          if pacman["valgrind"]: -            cmd.append("valgrind --tool=memcheck --leak-check=full --show-reachable=yes") +            cmd.append("valgrind -q --tool=memcheck --leak-check=full --show-reachable=yes")          cmd.append("\"%s\" --config=\"%s\" --root=\"%s\" --dbpath=\"%s\" --cachedir=\"%s\"" \                     % (pacman["bin"],                         os.path.join(self.root, PACCONF), @@ -233,11 +233,6 @@ class pmtest:          vprint("\tretcode = %s" % self.retcode)          os.chdir(curdir) -        # Check if pacman failed because of bad permissions -        if self.retcode and not pacman["nolog"] \ -           and grep(os.path.join(self.root, LOGFILE), -                    "you cannot perform this operation unless you are root"): -            print "\tERROR: pacman support for fakeroot is not disabled"          # Check if the lock is still there          if os.path.isfile(PM_LOCK):              print "\tERROR: %s not removed" % PM_LOCK diff --git a/pactest/tests/TESTS b/pactest/tests/TESTS deleted file mode 100644 index e09a78b9..00000000 --- a/pactest/tests/TESTS +++ /dev/null @@ -1,63 +0,0 @@ -TODO: this is really outdated, needs regeneration (after we rename tests) - -add001: Install a package -add002: Install a package (already installed) -add003: Install a set of packages -add004: Install a set of the same package at different versions -add010: Install a package with a filesystem conflict -add011: Install a package with a filesystem conflict (--force) -add012: Install two packages with a conflicting file -add013: Install two packages with a conflicting file (--force) -add020: Install a package with an existing file -add021: Install a package with an existing file (new modified) -add030: Freshen a package -add031: Freshen a package (installed is newer) -add032: Freshen a package (installed is newer) -add040: Install a package with a missing dependency -add041: Install a package with a missing dependency (nodeps) -add042: Install a package with cascaded dependencies -add050: Install a package with a file in NoUpgrade -add060: Install a package with a file in NoExtract -query001: Query a package -remove010: Remove a package, with a file marked for backup -remove011: Remove a package, with a modified file marked for backup -remove020: Remove a package, with a file marked for backup (--nosave) -remove021: Remove a package, with a modified  file marked for backup (--nosave) -smoke001: Install a thousand packages in a single transaction -sync001: Install a package from a sync db -sync002: Upgrade a package from a sync db -sync003: Install a package from a sync db, with a filesystem conflict -sync010: Install a package from a sync db, with its dependencies -sync040: Install two targets with a conflict -sync041: Install two conflicting targets -sync042: Install a sync package conflicting with a local one -sync043: Install a sync package conflicting with a local one -sync050: Install a virtual target (provided by a sync package) -sync100: Sysupgrade with a newer sync package -sync101: Sysupgrade with same version for local and sync packages -sync102: Sysupgrade with a newer local package -sync103: Sysupgrade with a local package not existing in sync db -sync110: Sysupgrade of a package pulling new dependencies -sync120: Sysupgrade of packages in 'IgnorePkg' -sync130: Sysupgrade with a sync package replacing a local one -sync131: Sysupgrade with a sync package replacing a set of local ones -sync132: Sysupgrade with a replacement for a local package out of date -sync133: Sysupgrade with a sync package replacing a local one in 'IgnorePkg' -sync134: Sysupgrade with a set of sync packages replacing a set local one -sync135: Sysupgrade with a set of sync packages replacing a set of local ones -sync897: System upgrade -sync898: System upgrade -sync899: System upgrade -sync990: Sync a package pulling a dependency conflicting with a target -sync992: Sync a package pulling a conflicting dependency -sync999: System upgrade -upgrade001: Upgrade a package (newer version) -upgrade002: Upgrade a package (same version) -upgrade003: Upgrade a package (lesser version) -upgrade004: Upgrade a package (not installed) -upgrade010: Upgrade a package, with a file in NoUpgrade -upgrade020: Upgrade a package, with a file in 'backup' (new modified) -upgrade021: Upgrade a package, with a file in 'backup' (local modified, new unchanged) -upgrade022: Upgrade a package, with a file in 'backup' (local and new modified) -upgrade030: Upgrade packages with various reasons -upgrade040: file relocation 1 diff --git a/pactest/tests/add001.py b/pactest/tests/add001.py deleted file mode 100644 index 3dde4061..00000000 --- a/pactest/tests/add001.py +++ /dev/null @@ -1,13 +0,0 @@ -self.description = "Install a simple package with two files" - -p = pmpkg("dummy") -p.files = ["bin/dummy", -           "usr/man/man1/dummy.1"] -self.addpkg(p) - -self.args = "-A %s" % p.filename() - -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_EXIST=dummy") -for f in p.files: -	self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/add002.py b/pactest/tests/add002.py deleted file mode 100644 index f6bc91a2..00000000 --- a/pactest/tests/add002.py +++ /dev/null @@ -1,18 +0,0 @@ -self.description = "Install an already-installed package" - -lp = pmpkg("dummy") -lp.files = ["bin/dummy", -            "usr/man/man1/dummy.1"] -self.addpkg2db("local", lp) - -p = pmpkg("dummy") -p.files = ["bin/dummy", -           "usr/man/man1/dummy.1"] -self.addpkg(p) - -self.args = "-A %s" % p.filename() - -self.addrule("PACMAN_RETCODE=1") -self.addrule("!PKG_MODIFIED=dummy") -for f in lp.files: -	self.addrule("!FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/add004.py b/pactest/tests/add004.py deleted file mode 100644 index d0188563..00000000 --- a/pactest/tests/add004.py +++ /dev/null @@ -1,18 +0,0 @@ -self.description = "Install three of the same package at different versions" - -p1 = pmpkg("dummy", "1.0-2") -p1.files = ["bin/dummy"] -p2 = pmpkg("dummy", "2.0-1") -p2.files = ["bin/dummy"] -p3 = pmpkg("dummy") -p3.files = ["bin/dummy"] - -for p in p1, p2, p3: -	self.addpkg(p) - -self.args = "-A %s" % " ".join([p.filename() for p in p1, p2, p3]) - -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_VERSION=dummy|2.0-1") -for f in p2.files: -	self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/add010.py b/pactest/tests/add010.py deleted file mode 100644 index a7874746..00000000 --- a/pactest/tests/add010.py +++ /dev/null @@ -1,15 +0,0 @@ -self.description = "Install a package with a filesystem conflict" - -p = pmpkg("dummy") -p.files = ["bin/dummy", -           "usr/man/man1/dummy.1"] -self.addpkg(p) - -self.filesystem = ["bin/dummy"] - -self.args = "-A %s" % p.filename() - -self.addrule("PACMAN_RETCODE=1") -self.addrule("!PKG_EXIST=dummy") -self.addrule("!FILE_MODIFIED=bin/dummy") -self.addrule("!FILE_EXIST=usr/man/man1/dummy.1") diff --git a/pactest/tests/add050.py b/pactest/tests/add050.py deleted file mode 100644 index b48459ab..00000000 --- a/pactest/tests/add050.py +++ /dev/null @@ -1,17 +0,0 @@ -self.description = "Install a package with a file in NoUpgrade" - -p = pmpkg("dummy") -p.files = ["etc/dummy.conf"] -p.backup = ["etc/dummy.conf"] -self.addpkg(p) - -self.filesystem = ["etc/dummy.conf"] - -self.option["noupgrade"] = ["etc/dummy.conf"] - -self.args = "-Af %s" % p.filename() - -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_EXIST=dummy") -self.addrule("!FILE_MODIFIED=etc/dummy.conf") -self.addrule("FILE_PACNEW=etc/dummy.conf") diff --git a/pactest/tests/depconflict110.py b/pactest/tests/depconflict110.py index 2e326f52..fd56fa89 100644 --- a/pactest/tests/depconflict110.py +++ b/pactest/tests/depconflict110.py @@ -7,7 +7,7 @@ self.addpkg(p);  lp = pmpkg("pkg2", "1.0-1")  self.addpkg2db("local", lp) -self.args = "-A %s" % p.filename() +self.args = "-U %s" % p.filename()  self.addrule("PACMAN_RETCODE=1")  self.addrule("!PKG_EXIST=pkg1")  self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/depconflict111.py b/pactest/tests/depconflict111.py index 6f95733b..0d11dd92 100644 --- a/pactest/tests/depconflict111.py +++ b/pactest/tests/depconflict111.py @@ -7,7 +7,7 @@ self.addpkg(p);  lp = pmpkg("pkg2", "1.0-1")  self.addpkg2db("local", lp) -self.args = "-A %s" % p.filename() +self.args = "-U %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_EXIST=pkg1")  self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/deptest001.py b/pactest/tests/deptest001.py index db0b7684..18569bea 100644 --- a/pactest/tests/deptest001.py +++ b/pactest/tests/deptest001.py @@ -1,20 +1,16 @@  self.description = "test deptest (-T) functionality" -sp1 = pmpkg("pkg1") -sp1.depends = ["dep"] -self.addpkg2db("sync", sp1) +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) -sp1dep = pmpkg("dep") -self.addpkg2db("sync", sp1dep) +lp3 = pmpkg("pkg3", "2.0-1") +lp3.provides = ("prov=3.0") +self.addpkg2db("local", lp3) -sp2 = pmpkg("pkg2") -self.addpkg2db("sync", sp2) - -lp2 = pmpkg("pkg2") -self.addpkg2db("local", lp2) - -self.args = "-T pkg1 pkg2" +self.args = "-T pkg1 pkg2 pkg3\>2.1 prov\>\=3.0"  self.addrule("PACMAN_RETCODE=127") -self.addrule("PACMAN_OUTPUT=pkg1") -self.addrule("!PACMAN_OUTPUT=pkg2") +self.addrule("!PACMAN_OUTPUT=pkg1") +self.addrule("PACMAN_OUTPUT=pkg2") +self.addrule("PACMAN_OUTPUT=pkg3") +self.addrule("!PACMAN_OUTPUT=prov") diff --git a/pactest/tests/fileconflict001.py b/pactest/tests/fileconflict001.py index 8aca9a0a..4c2069ee 100644 --- a/pactest/tests/fileconflict001.py +++ b/pactest/tests/fileconflict001.py @@ -13,7 +13,7 @@ p2 = pmpkg("pkg2")  p2.files = ["dir/symdir/file"]  self.addpkg(p2) -self.args = "-A %s" % " ".join([p.filename() for p in p1, p2]) +self.args = "-U %s" % " ".join([p.filename() for p in p1, p2])  self.addrule("PACMAN_RETCODE=1")  self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/fileconflict002.py b/pactest/tests/fileconflict002.py index da04e332..c54f6daf 100644 --- a/pactest/tests/fileconflict002.py +++ b/pactest/tests/fileconflict002.py @@ -9,7 +9,7 @@ p2 = pmpkg("pkg2")  p2.files = ["dir/symdir/file"]  self.addpkg(p2) -self.args = "-A %s" % " ".join([p.filename() for p in p1, p2]) +self.args = "-U %s" % " ".join([p.filename() for p in p1, p2])  self.addrule("PACMAN_RETCODE=1")  self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/ldconfig001.py b/pactest/tests/ldconfig001.py index aced413b..9ac2ff35 100644 --- a/pactest/tests/ldconfig001.py +++ b/pactest/tests/ldconfig001.py @@ -6,7 +6,7 @@ p = pmpkg("dummy")  self.addpkg(p)  # --debug is necessary to check PACMAN_OUTPUT -self.args = "--debug -A %s" % p.filename() +self.args = "--debug -U %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PACMAN_OUTPUT=ldconfig") diff --git a/pactest/tests/mode001.py b/pactest/tests/mode001.py index ff245a2c..4ec11e10 100644 --- a/pactest/tests/mode001.py +++ b/pactest/tests/mode001.py @@ -1,7 +1,7 @@  self.description = "Check the mode of default files in a package"  p = pmpkg("pkg1") -p.files = ["bin/foo" +p.files = ["bin/foo",             "bin/bar"]  self.addpkg(p) diff --git a/pactest/tests/mode002.py b/pactest/tests/mode002.py new file mode 100644 index 00000000..cc4a8fe8 --- /dev/null +++ b/pactest/tests/mode002.py @@ -0,0 +1,12 @@ +self.description = "Check execute mode on files in a package" + +p = pmpkg("pkg1") +p.files = ["bin/foo|755", +           "bin/bar|755"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("FILE_MODE=bin/foo|755") +self.addrule("FILE_MODE=bin/bar|755") diff --git a/pactest/tests/mode003.py b/pactest/tests/mode003.py new file mode 100644 index 00000000..1193a5cf --- /dev/null +++ b/pactest/tests/mode003.py @@ -0,0 +1,20 @@ +self.description = "Backup file permissions test (same as orig)" + +lp = pmpkg("filesystem") +lp.files = ["etc/profile|666"] +lp.backup = ["etc/profile*"] +self.addpkg2db("local", lp) + +p = pmpkg("filesystem", "1.0-2") +p.files = ["etc/profile|666**"] +p.backup = ["etc/profile"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!FILE_PACSAVE=etc/profile") +self.addrule("FILE_PACNEW=etc/profile") +self.addrule("FILE_EXIST=etc/profile") +self.addrule("FILE_MODE=etc/profile|666") +self.addrule("FILE_MODE=etc/profile.pacnew|666") diff --git a/pactest/tests/query003.py b/pactest/tests/query003.py index ea113081..41b8a45b 100644 --- a/pactest/tests/query003.py +++ b/pactest/tests/query003.py @@ -2,6 +2,7 @@ self.description = "Query search for a package"  p = pmpkg("foobar")  p.files = ["bin/foobar"] +p.groups = ["group1", "group2"]  self.addpkg2db("local", p)  self.args = "-Qs %s" % p.name diff --git a/pactest/tests/reason001.py b/pactest/tests/reason001.py new file mode 100644 index 00000000..40433f5e --- /dev/null +++ b/pactest/tests/reason001.py @@ -0,0 +1,16 @@ +self.description = "Copy reason (to-be-replaced -> replacement)" + +sp = pmpkg("libfoo-ng") +sp.replaces = [ "libfoo" ] +self.addpkg2db("sync", sp) + +lp = pmpkg("libfoo") +lp.reason = 1 +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=libfoo") +self.addrule("PKG_EXIST=libfoo-ng") +self.addrule("PKG_REASON=libfoo-ng|1") diff --git a/pactest/tests/remove001.py b/pactest/tests/remove001.py index 809bfdb7..d20dd079 100644 --- a/pactest/tests/remove001.py +++ b/pactest/tests/remove001.py @@ -1,4 +1,3 @@ -# If someone else can come up with a better name, please do so  self.description = "Remove a package listed 5 times"  p = pmpkg("foo") @@ -6,5 +5,5 @@ self.addpkg2db("local", p)  self.args = "-R " + "foo "*5 -self.addrule("PACMAN_RETCODE=0") -self.addrule("!PKG_EXISTS=foo") +self.addrule("PACMAN_RETCODE=1") +self.addrule("PKG_EXISTS=foo") diff --git a/pactest/tests/remove030.py b/pactest/tests/remove030.py index cc23f144..9e2b9da5 100644 --- a/pactest/tests/remove030.py +++ b/pactest/tests/remove030.py @@ -3,7 +3,7 @@ self.description = "Remove a package in HoldPkg"  p1 = pmpkg("dummy")  self.addpkg2db("local", p1) -self.option["holdpkg"] = ["dummy"] +self.option["HoldPkg"] = ["dummy"]  self.args = "-R %s" % p1.name diff --git a/pactest/tests/remove049.py b/pactest/tests/remove049.py new file mode 100644 index 00000000..724f8da2 --- /dev/null +++ b/pactest/tests/remove049.py @@ -0,0 +1,19 @@ +self.description = "-Ru test" + +lp1 = pmpkg("pkg1") +lp1.requiredby = [ "pkg3" ] +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +self.addpkg2db("local", lp2) + +lp3 = pmpkg("pkg3") +lp3.depends = [ "pkg1" ] +self.addpkg2db("local", lp3) + +self.args = "-Ru pkg1 pkg2" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg3")
\ No newline at end of file diff --git a/pactest/tests/remove050.py b/pactest/tests/remove050.py new file mode 100644 index 00000000..44b0d18c --- /dev/null +++ b/pactest/tests/remove050.py @@ -0,0 +1,20 @@ +self.description = "-Rs test (exclude explicit)" + +lp1 = pmpkg("pkg1") +lp1.depends = ["pkg2" , "pkg3"] +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +lp2.reason = 1 +self.addpkg2db("local", lp2) + +lp3 = pmpkg("pkg3") +lp3.reason = 0 +self.addpkg2db("local", lp3) + +self.args = "-Rs %s" % lp1.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg3") diff --git a/pactest/tests/remove051.py b/pactest/tests/remove051.py new file mode 100644 index 00000000..bba87bba --- /dev/null +++ b/pactest/tests/remove051.py @@ -0,0 +1,20 @@ +self.description = "-Rss test (include explicit)" + +lp1 = pmpkg("pkg1") +lp1.depends = ["pkg2" , "pkg3"] +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +lp2.reason = 1 +self.addpkg2db("local", lp2) + +lp3 = pmpkg("pkg3") +lp3.reason = 0 +self.addpkg2db("local", lp3) + +self.args = "-Rss %s" % lp1.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") +self.addrule("!PKG_EXIST=pkg3") diff --git a/pactest/tests/smoke001.py b/pactest/tests/smoke001.py index 71a08d3f..c6636391 100644 --- a/pactest/tests/smoke001.py +++ b/pactest/tests/smoke001.py @@ -12,7 +12,7 @@ for i in range(1000):  _list = []  [_list.append(p.filename()) for p in self.localpkgs] -self.args = "-A %s" % " ".join(_list) +self.args = "-U %s" % " ".join(_list)  self.addrule("PACMAN_RETCODE=0")  #for i in range(1000): diff --git a/pactest/tests/sync021.py b/pactest/tests/sync021.py index a4073eed..4c664d8e 100644 --- a/pactest/tests/sync021.py +++ b/pactest/tests/sync021.py @@ -12,7 +12,7 @@ sp3.groups = ["grp"]  for p in sp1, sp2, sp3:  	self.addpkg2db("sync", p); -self.option["ignorepkg"] = ["pkg2"] +self.option["IgnorePkg"] = ["pkg2"]  self.args = "-S grp" diff --git a/pactest/tests/sync031.py b/pactest/tests/sync031.py new file mode 100644 index 00000000..4aa2ee39 --- /dev/null +++ b/pactest/tests/sync031.py @@ -0,0 +1,19 @@ +self.description = "Sync packages explicitly" + +lp1 = pmpkg("pkg1") +lp1.reason = 1 +self.addpkg2db("local", lp1) + +p1 = pmpkg("pkg1", "1.0-2") +p2 = pmpkg("pkg2", "1.0-2") + +for p in p1, p2: +	self.addpkg2db("sync", p) + +self.args = "-S --asexplicit %s" % " ".join([p.name for p in p1, p2]) + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|1.0-2") +self.addrule("PKG_VERSION=pkg2|1.0-2") +self.addrule("PKG_REASON=pkg1|0") +self.addrule("PKG_REASON=pkg2|0") diff --git a/pactest/tests/sync1001.py b/pactest/tests/sync1001.py deleted file mode 100644 index 6c4aabcf..00000000 --- a/pactest/tests/sync1001.py +++ /dev/null @@ -1,18 +0,0 @@ -self.description = "Test -Se (ensure specified package is not installed)" - -sp1 = pmpkg("dummy") -sp1.depends = [ "dep1", "dep2" ] -self.addpkg2db("sync", sp1) - -sp2 = pmpkg("dep1") -self.addpkg2db("sync", sp2) - -sp3 = pmpkg("dep2") -self.addpkg2db("sync", sp3) - -self.args = "-Se dummy" - -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_EXIST=dep1") -self.addrule("PKG_EXIST=dep2") -self.addrule("!PKG_EXIST=dummy") diff --git a/pactest/tests/sync1002.py b/pactest/tests/sync1002.py deleted file mode 100644 index c158838b..00000000 --- a/pactest/tests/sync1002.py +++ /dev/null @@ -1,19 +0,0 @@ -self.description = "Test -Se (resolve the dependencies' dependencies )" - -sp1 = pmpkg("pkg1") -sp1.depends = [ "pkg2" ] -self.addpkg2db("sync", sp1) - -sp2 = pmpkg("pkg2") -sp2.depends = [ "pkg3" ] -self.addpkg2db("sync", sp2) - -sp3 = pmpkg("pkg3") -self.addpkg2db("sync", sp3) - -self.args = "-Se pkg1 pkg3" - -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_EXIST=pkg2") -self.addrule("PKG_EXIST=pkg3") -self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/sync1006.py b/pactest/tests/sync1006.py deleted file mode 100644 index c331f42e..00000000 --- a/pactest/tests/sync1006.py +++ /dev/null @@ -1,14 +0,0 @@ -self.description = "Conflicting package names in sync repos (diff versions)" - -sp1 = pmpkg("pkg", "1.0-1") -sp1.provides = [ "provision1" ] -self.addpkg2db("sync1", sp1) - -sp2 = pmpkg("pkg", "2.0-1") -sp2.provides = [ "provision2" ] -self.addpkg2db("sync2", sp2) - -self.args = "-S provision1 provision2" - -self.addrule("PACMAN_RETCODE=1") -self.addrule("!PKG_EXIST=pkg") diff --git a/pactest/tests/sync1005.py b/pactest/tests/sync1008.py index 4fa82478..a6064597 100644 --- a/pactest/tests/sync1005.py +++ b/pactest/tests/sync1008.py @@ -1,14 +1,19 @@  self.description = "Conflicting package names in sync repos" -sp1 = pmpkg("pkg") +sp1 = pmpkg("cpkg", "1.0-1")  sp1.provides = [ "provision1" ]  self.addpkg2db("sync1", sp1) -sp2 = pmpkg("pkg") +sp2 = pmpkg("cpkg", "2.0-1")  sp2.provides = [ "provision2" ]  self.addpkg2db("sync2", sp2) -self.args = "-S provision1 provision2" +sp3 = pmpkg("pkg") +sp3.depends = [ "provision1" , "provision2" ] +self.addpkg2db("sync1", sp3) + +self.args = "-S pkg"  self.addrule("PACMAN_RETCODE=1")  self.addrule("!PKG_EXIST=pkg") +self.addrule("!PKG_EXIST=cpkg") diff --git a/pactest/tests/sync1101.py b/pactest/tests/sync1101.py index ba2ad44f..e3ed0f0f 100644 --- a/pactest/tests/sync1101.py +++ b/pactest/tests/sync1101.py @@ -1,6 +1,7 @@  self.description = "Search for package from a sync db"  sp = pmpkg("dummy") +sp.groups = ["group1", "group2"]  sp.files = ["bin/dummy",              "usr/man/man1/dummy.1"]  self.addpkg2db("sync", sp) diff --git a/pactest/tests/sync120.py b/pactest/tests/sync120.py index b8fc6747..994e440e 100644 --- a/pactest/tests/sync120.py +++ b/pactest/tests/sync120.py @@ -12,7 +12,7 @@ lp2 = pmpkg("pkg2")  for p in lp1, lp2:  	self.addpkg2db("local", p) -self.option["ignorepkg"] = ["pkg2"] +self.option["IgnorePkg"] = ["pkg2"]  self.args = "-Su" diff --git a/pactest/tests/sync133.py b/pactest/tests/sync133.py index b852a7fc..cea603b8 100644 --- a/pactest/tests/sync133.py +++ b/pactest/tests/sync133.py @@ -9,7 +9,7 @@ lp = pmpkg("pkg1")  self.addpkg2db("local", lp) -self.option["ignorepkg"] = ["pkg1"] +self.option["IgnorePkg"] = ["pkg1"]  self.args = "-Su" diff --git a/pactest/tests/sync138.py b/pactest/tests/sync138.py index 410c7f07..e67c4f46 100644 --- a/pactest/tests/sync138.py +++ b/pactest/tests/sync138.py @@ -13,7 +13,7 @@ lp2 = pmpkg("pkg2")  for p in lp1, lp2:  	self.addpkg2db("local", p) -self.option["ignoregroup"] = ["grp"] +self.option["IgnoreGroup"] = ["grp"]  self.args = "-Su" diff --git a/pactest/tests/sync893.py b/pactest/tests/sync893.py index 9420b74c..1c8494a3 100644 --- a/pactest/tests/sync893.py +++ b/pactest/tests/sync893.py @@ -15,6 +15,6 @@ self.addpkg2db("local", lp2)  self.args = "-S %s" % " ".join([p.name for p in sp1, sp2]) -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1")  self.addrule("PKG_EXIST=pkg1") -self.addrule("!PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/sync897.py b/pactest/tests/sync897.py index 3cf43929..f7bd3d71 100644 --- a/pactest/tests/sync897.py +++ b/pactest/tests/sync897.py @@ -18,7 +18,7 @@ self.addpkg2db("local", lp3)  self.args = "-Su" -self.addrule("PACMAN_RETCODE=0") +self.addrule("PACMAN_RETCODE=1")  self.addrule("PKG_EXIST=pkg1") -self.addrule("!PKG_EXIST=pkg2") -self.addrule("!PKG_EXIST=pkg3") +self.addrule("PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg3") diff --git a/pactest/tests/add003.py b/pactest/tests/upgrade005.py index 4f8ae600..0f8c13ef 100644 --- a/pactest/tests/add003.py +++ b/pactest/tests/upgrade005.py @@ -14,7 +14,7 @@ p3.files = ["bin/pkg3", "usr/man/man1/pkg3.1"]  for p in p1, p2, p3:  	self.addpkg(p) -self.args = "-A %s" % " ".join([p.filename() for p in p1, p2, p3]) +self.args = "-U %s" % " ".join([p.filename() for p in p1, p2, p3])  self.addrule("PACMAN_RETCODE=0")  for p in p1, p2, p3: diff --git a/pactest/tests/upgrade010.py b/pactest/tests/upgrade010.py index 633ef7e4..3d8b21e1 100644 --- a/pactest/tests/upgrade010.py +++ b/pactest/tests/upgrade010.py @@ -8,7 +8,7 @@ p = pmpkg("dummy", "1.0-2")  p.files = ["etc/dummy.conf"]  self.addpkg(p) -self.option["noupgrade"] = ["etc/dummy.conf"] +self.option["NoUpgrade"] = ["etc/dummy.conf"]  self.args = "-U %s" % p.filename() diff --git a/pactest/tests/add011.py b/pactest/tests/upgrade012.py index 5d2ae43f..dba8dc18 100644 --- a/pactest/tests/add011.py +++ b/pactest/tests/upgrade012.py @@ -6,7 +6,7 @@ self.addpkg(p)  self.filesystem = ["bin/dummy"] -self.args = "-Af %s" % p.filename() +self.args = "-Uf %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_EXIST=dummy") diff --git a/pactest/tests/add012.py b/pactest/tests/upgrade013.py index 291d1fba..5a327599 100644 --- a/pactest/tests/add012.py +++ b/pactest/tests/upgrade013.py @@ -13,7 +13,7 @@ p2.files = ["bin/foobar",  for p in p1, p2:  	self.addpkg(p) -self.args = "-A %s" % " ".join([p.filename() for p in p1, p2]) +self.args = "-U %s" % " ".join([p.filename() for p in p1, p2])  self.addrule("PACMAN_RETCODE=1")  self.addrule("!PKG_EXIST=dummy") diff --git a/pactest/tests/add013.py b/pactest/tests/upgrade014.py index 547ce001..1632dd36 100644 --- a/pactest/tests/add013.py +++ b/pactest/tests/upgrade014.py @@ -13,7 +13,7 @@ p2.files = ["bin/foobar",  for p in p1, p2:  	self.addpkg(p) -self.args = "-Af %s" % " ".join([p.filename() for p in p1, p2]) +self.args = "-Uf %s" % " ".join([p.filename() for p in p1, p2])  self.addrule("PACMAN_RETCODE=0")  for p in p1, p2: diff --git a/pactest/tests/add020.py b/pactest/tests/upgrade015.py index 8a2f4a71..22f7c36b 100644 --- a/pactest/tests/add020.py +++ b/pactest/tests/upgrade015.py @@ -6,7 +6,7 @@ self.addpkg(p)  self.filesystem = ["etc/dummy.conf"] -self.args = "-Af %s" % p.filename() +self.args = "-Uf %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_EXIST=dummy") diff --git a/pactest/tests/add021.py b/pactest/tests/upgrade016.py index a6dda963..dd31c9ab 100644 --- a/pactest/tests/add021.py +++ b/pactest/tests/upgrade016.py @@ -7,7 +7,7 @@ self.addpkg(p)  self.filesystem = ["etc/dummy.conf"] -self.args = "-Af %s" % p.filename() +self.args = "-Uf %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_EXIST=dummy") diff --git a/pactest/tests/upgrade032.py b/pactest/tests/upgrade032.py new file mode 100644 index 00000000..85e048e0 --- /dev/null +++ b/pactest/tests/upgrade032.py @@ -0,0 +1,19 @@ +self.description = "Install packages explicitly" + +lp1 = pmpkg("pkg1") +lp1.reason = 1 +self.addpkg2db("local", lp1) + +p1 = pmpkg("pkg1", "1.0-2") +p2 = pmpkg("pkg2", "1.0-2") + +for p in p1, p2: +	self.addpkg(p) + +self.args = "-U --asexplicit %s" % " ".join([p.filename() for p in p1, p2]) + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|1.0-2") +self.addrule("PKG_VERSION=pkg2|1.0-2") +self.addrule("PKG_REASON=pkg1|0") +self.addrule("PKG_REASON=pkg2|0") diff --git a/pactest/tests/add060.py b/pactest/tests/upgrade070.py index 4c5f17da..01f0ba48 100644 --- a/pactest/tests/add060.py +++ b/pactest/tests/upgrade070.py @@ -5,9 +5,9 @@ p.files = ["bin/dummy",             "usr/man/man1/dummy.1"]  self.addpkg(p) -self.option["noextract"] = ["usr/man/man1/dummy.1"] +self.option["NoExtract"] = ["usr/man/man1/dummy.1"] -self.args = "-A %s" % p.filename() +self.args = "-U %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_EXIST=dummy") diff --git a/pactest/tests/add040.py b/pactest/tests/upgrade071.py index 6d6da602..1f21c558 100644 --- a/pactest/tests/add040.py +++ b/pactest/tests/upgrade071.py @@ -6,7 +6,7 @@ p.files = ["bin/dummy",  p.depends = ["dep1"]  self.addpkg(p) -self.args = "-A %s" % p.filename() +self.args = "-U %s" % p.filename()  self.addrule("PACMAN_RETCODE=1")  self.addrule("!PKG_EXIST=dummy") diff --git a/pactest/tests/add041.py b/pactest/tests/upgrade072.py index af3ffe46..f88e150c 100644 --- a/pactest/tests/add041.py +++ b/pactest/tests/upgrade072.py @@ -6,7 +6,7 @@ p.files = ["bin/dummy",  p.depends = ["dep1"]  self.addpkg(p) -self.args = "-Ad %s" % p.filename() +self.args = "-Ud %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_EXIST=dummy") diff --git a/pactest/tests/add042.py b/pactest/tests/upgrade073.py index 48104b0c..3486c417 100644 --- a/pactest/tests/add042.py +++ b/pactest/tests/upgrade073.py @@ -15,7 +15,7 @@ p3.files = ["bin/dep2"]  for p in p1, p2, p3:  	self.addpkg(p) -self.args = "-A %s" % " ".join([p.filename() for p in p1, p2, p3]) +self.args = "-U %s" % " ".join([p.filename() for p in p1, p2, p3])  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_VERSION=dummy|1.0-2") diff --git a/pactest/tests/add046.py b/pactest/tests/upgrade074.py index 5f967cbe..ca052855 100644 --- a/pactest/tests/add046.py +++ b/pactest/tests/upgrade074.py @@ -7,7 +7,7 @@ self.addpkg(p)  lp = pmpkg("pkg2", "1.9b-3")  self.addpkg2db("local", lp) -self.args = "-A %s" % p.filename() +self.args = "-U %s" % p.filename()  self.addrule("PACMAN_RETCODE=0")  self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/add047.py b/pactest/tests/upgrade075.py index 153364a5..8d2f3fc4 100644 --- a/pactest/tests/add047.py +++ b/pactest/tests/upgrade075.py @@ -7,7 +7,7 @@ self.addpkg(p)  lp = pmpkg("pkg2", "2.0-3")  self.addpkg2db("local", lp) -self.args = "-A %s" % p.filename() +self.args = "-U %s" % p.filename()  self.addrule("PACMAN_RETCODE=1")  self.addrule("!PKG_EXIST=pkg1") diff --git a/pactest/tests/xfercommand001.py b/pactest/tests/xfercommand001.py index a9c41d8c..a645cf7f 100644 --- a/pactest/tests/xfercommand001.py +++ b/pactest/tests/xfercommand001.py @@ -3,7 +3,7 @@ self.description = "Quick check for using XferCommand"  # this setting forces us to download packages  self.cachepkgs = False  #wget doesn't support file:// urls.  curl does -self.option['xfercommand'] = ['/usr/bin/curl %u > %o'] +self.option['XferCommand'] = ['/usr/bin/curl %u > %o']  numpkgs = 10  pkgnames = [] diff --git a/pactest/util.py b/pactest/util.py index 2a6ff4e7..c6d5a594 100755 --- a/pactest/util.py +++ b/pactest/util.py @@ -58,35 +58,35 @@ def vprint(msg):  def getfilename(name):      """      """ -    filename = "" -    link = "" -    if name.find(" -> ") != -1: -        filename, link = name.split(" -> ") -    elif name[-1] == "*": -        filename = name.rstrip("*") -    else: -        filename = name +    filename = name +    extra = "" +    if filename[-1] == "*": +        filename = filename.rstrip("*") +    if filename.find(" -> ") != -1: +        filename, extra = filename.split(" -> ") +    elif filename.find("|") != -1: +        filename, extra = filename.split("|")      return filename  def mkfile(name, data = ""):      """      """ - -    isaltered = 0      isdir = 0      islink = 0 +    setperms = 0 +    filename = name      link = "" -    filename = "" +    perms = "" -    if name.find(" -> ") != -1: +    if filename[-1] == "*": +        filename = filename.rstrip("*") +    if filename.find(" -> ") != -1:          islink = 1 -        filename, link = name.split(" -> ") -    elif name[-1] == "*": -        isaltered = 1 -        filename = name.rstrip("*") -    else: -        filename = name -    if name[-1] == "/": +        filename, link = filename.split(" -> ") +    elif filename.find("|") != -1: +        setperms = 1 +        filename, perms = filename.split("|") +    if filename[-1] == "/":          isdir = 1      if isdir: @@ -114,6 +114,8 @@ def mkfile(name, data = ""):              if data[-1] != "\n":                  fd.write("\n")          fd.close() +        if setperms: +            os.chmod(filename, int(perms, 8))  def mkdescfile(filename, pkg):      """ @@ -181,7 +183,7 @@ def mkcfgfile(filename, root, option, db):      # Repositories      data.extend(["[%s]\n" \ -                 "server = file://%s\n" \ +                 "Server = file://%s\n" \                   % (value.treename, \                      os.path.join(root, SYNCREPO, value.treename)) \                   for key, value in db.iteritems() if key != "local"]) diff --git a/po/POTFILES.in b/po/POTFILES.in index 359a8041..cf6e9506 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,7 +1,6 @@  # List of source files with translatable strings  # pacman frontend source files -src/pacman/add.c  src/pacman/callback.c  src/pacman/conf.c  src/pacman/deptest.c @@ -11,11 +10,10 @@ src/pacman/query.c  src/pacman/remove.c  src/pacman/sync.c  src/pacman/util.c +src/pacman/upgrade.c  # scripts with gettext translations -scripts/gensync.sh.in  scripts/makepkg.sh.in  scripts/pacman-optimize.sh.in  scripts/repo-add.sh.in  scripts/repo-remove.sh.in -scripts/updatesync.sh.in diff --git a/scripts/.gitignore b/scripts/.gitignore index 53164a41..f2f19fd8 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -1,7 +1,5 @@ -gensync  makepkg  pacman-optimize  rankmirrors  repo-add  repo-remove -updatesync diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 24b9c12d..3185a476 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -2,22 +2,18 @@  AUTOMAKE_OPTIONS = std-options  bin_SCRIPTS = \ -	gensync \  	makepkg \  	pacman-optimize \  	rankmirrors \  	repo-add \ -	repo-remove \ -	updatesync +	repo-remove  EXTRA_DIST = \ -	gensync.sh.in \  	makepkg.sh.in \  	pacman-optimize.sh.in \  	rankmirrors.py.in \  	repo-add.sh.in \ -	repo-remove.sh.in \ -	updatesync.sh.in +	repo-remove.sh.in  # Files that should be removed, but which Automake does not know.  MOSTLYCLEANFILES = $(bin_SCRIPTS) *.tmp @@ -48,13 +44,11 @@ $(bin_SCRIPTS): Makefile  	chmod a-w $@.tmp  	mv $@.tmp $@ -gensync: $(srcdir)/gensync.sh.in  makepkg: $(srcdir)/makepkg.sh.in  pacman-optimize: $(srcdir)/pacman-optimize.sh.in  rankmirrors: $(srcdir)/rankmirrors.py.in  repo-add: $(srcdir)/repo-add.sh.in  repo-remove: $(srcdir)/repo-remove.sh.in  re-pacman: $(srcdir)/re-pacman.sh.in -updatesync: $(srcdir)/updatesync.sh.in  # vim:set ts=2 sw=2 noet: diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 54676667..7db8b4d7 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -299,6 +299,20 @@ get_downloadclient() {  	echo "$agent"  } +get_downloadcmd() { +	local dlagent=$1 +	local netfile=$2 +	local file=$3 + +	if echo "$dlagent" | grep -q "%u" ; then +		local dlcmd=$(echo "$dlagent" | sed "s|%o|$file.part|" | sed "s|%u|$netfile|") +	else +		local dlcmd="$dlagent $netfile" +	fi + +	echo "$dlcmd" +} +  check_deps() {  	[ $# -gt 0 ] || return @@ -471,17 +485,20 @@ download_sources() {  		fi  		# find the client we should use for this URL -		local dlclient=$(get_downloadclient $netfile) || exit $? +		local dlclient=$(get_downloadclient "$netfile") || exit $?  		msg2 "$(gettext "Downloading %s...")" "$file"  		# fix flyspray bug #3289  		local ret=0 -		$dlclient "$netfile" || ret=$? +		$(get_downloadcmd "$dlclient" "$netfile" "$file") || ret=$?  		if [ $ret -gt 0 ]; then  			error "$(gettext "Failure while downloading %s")" "$file"  			plain "$(gettext "Aborting...")"  			exit 1  		fi +		if echo "$dlclient" | grep -q "%o" ; then +			mv -f "$SRCDEST/$file.part" "$SRCDEST/$file" +		fi  		cp -s --remove-destination "$SRCDEST/$file" "$srcdir/"  	done @@ -716,37 +733,41 @@ tidy_install() {  		rm -rf ${DOC_DIRS[@]}  	fi -	msg2 "$(gettext "Compressing man pages...")" -	local manpage mandirs ext file link hardlinks hl -	mandirs="usr/man usr/share/man usr/local/man usr/local/share/man opt/*/man" -	find ${mandirs} -type f 2>/dev/null | while read manpage ; do -		# check file still exists (potentially compressed with hard link) -		if [ -f ${manpage} ]; then -			ext="${manpage##*.}" -			file="${manpage##*/}" -			if [ "$ext" != "gz" -a "$ext" != "bz2" ]; then -				# update symlinks to this manpage -				find ${mandirs} -lname "$file" 2>/dev/null | while read link ; do -					rm -f "$link" -					ln -sf "${file}.gz" "${link}.gz" -				done -				# find hard links and remove them -				#   the '|| true' part keeps the script from bailing if find returned an -				#   error, such as when one of the man directories doesn't exist -				hardlinks="$(find ${mandirs} \! -name "$file" -samefile "$manpage" 2>/dev/null)" || true -				for hl in ${hardlinks}; do -					rm -f "${hl}"; -				done -				# compress the original -				gzip -9 "$manpage" -				# recreate hard links removed earlier -				for hl in ${hardlinks}; do -					ln "${manpage}.gz" "${hl}.gz" -					chmod 644 ${hl}.gz -				done +	if [ "$(check_option zipman)" = "y" ]; then +		msg2 "$(gettext "Compressing man pages...")" +		local manpage mandirs ext file link hardlinks hl +		mandirs="usr/man usr/share/man usr/local/man usr/local/share/man opt/*/man" +		find ${mandirs} -type f 2>/dev/null | +		while read manpage ; do +			# check file still exists (potentially compressed with hard link) +			if [ -f ${manpage} ]; then +				ext="${manpage##*.}" +				file="${manpage##*/}" +				if [ "$ext" != "gz" -a "$ext" != "bz2" ]; then +					# update symlinks to this manpage +					find ${mandirs} -lname "$file" 2>/dev/null | +					while read link ; do +						rm -f "$link" +						ln -sf "${file}.gz" "${link}.gz" +					done +					# find hard links and remove them +					#   the '|| true' part keeps the script from bailing if find returned an +					#   error, such as when one of the man directories doesn't exist +					hardlinks="$(find ${mandirs} \! -name "$file" -samefile "$manpage" 2>/dev/null)" || true +					for hl in ${hardlinks}; do +						rm -f "${hl}"; +					done +					# compress the original +					gzip -9 "$manpage" +					# recreate hard links removed earlier +					for hl in ${hardlinks}; do +						ln "${manpage}.gz" "${hl}.gz" +						chmod 644 ${hl}.gz +					done +				fi  			fi -		fi -	done +		done +	fi  	if [ "$(check_option strip)" = "y" ]; then diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index 63d94d37..f837262d 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -25,7 +25,6 @@ export TEXTDOMAINDIR='@localedir@'  myver='@PACKAGE_VERSION@'  confdir='@sysconfdir@' -FORCE=0  REPO_DB_FILE=""  # ensure we have a sane umask set @@ -54,14 +53,10 @@ error() {  # print usage instructions  usage() {  	printf "repo-add (pacman) %s\n\n" "$myver" -	printf "$(gettext "Usage: %s <path-to-db> [--force] <package> ...\n\n")" "$0" +	printf "$(gettext "Usage: %s <path-to-db> <package> ...\n\n")" "$0"  	printf "$(gettext "\  repo-add will update a package database by reading a package file.\n\  Multiple packages to add can be specified on the command line.\n\n")" -	printf "$(gettext "\ -The --force flag will add a 'force' entry to the sync database, which\n\ -tells pacman to skip its internal version number checking and update\n\ -the package regardless.\n\n")"  	echo "$(gettext "Example:  repo-add /path/to/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz")"  } @@ -209,7 +204,7 @@ db_write_entry()  	[ -n "$builddate" ] && echo -e "%BUILDDATE%\n$builddate\n" >>desc  	[ -n "$packager" ] && echo -e "%PACKAGER%\n$packager\n" >>desc  	write_list_entry "REPLACES" "$_replaces" "desc" -	[ $FORCE -eq 1 -o -n "$force" ] && echo -e "%FORCE%\n" >>desc +	[ -n "$force" ] && echo -e "%FORCE%\n" >>desc  	# create depends entry  	msg2 "$(gettext "Creating 'depends' db entry...")" @@ -298,7 +293,8 @@ success=0  # parse arguments  for arg in "$@"; do  	if [ "$arg" == "--force" -o "$arg" == "-f" ]; then -		FORCE=1 +		warning "$(gettext "the -f and --force options are no longer recognized")" +		msg2 "$(gettext "use options=(force) in the PKGBUILD instead")"  	elif [ -z "$REPO_DB_FILE" ]; then  		REPO_DB_FILE=$(readlink -f "$arg")  		if ! test_repo_db_file; then diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am index 5e287404..5d6fef3c 100644 --- a/src/pacman/Makefile.am +++ b/src/pacman/Makefile.am @@ -22,7 +22,6 @@ INCLUDES = -I$(top_srcdir)/lib/libalpm  AM_CFLAGS = -pedantic -D_GNU_SOURCE  pacman_SOURCES = \ -	add.c \  	conf.h conf.c \  	deptest.c \  	package.h package.c \ @@ -31,6 +30,7 @@ pacman_SOURCES = \  	remove.c \  	sync.c \  	callback.h callback.c \ +	upgrade.c \  	util.h util.c  LDADD = $(LTLIBINTL) $(top_builddir)/lib/libalpm/.libs/libalpm.la diff --git a/src/pacman/callback.c b/src/pacman/callback.c index a7686483..8a7af5c5 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -34,9 +34,6 @@  #include "util.h"  #include "conf.h" -/* TODO this should not have to be defined twice- trans.c & log.c */ -#define LOG_STR_LEN 256 -  /* download progress bar */  static float rate_last;  static int xfered_last; @@ -86,17 +83,14 @@ static float get_update_timediff(int first_call)  }  /* refactored from cb_trans_progress */ -static void fill_progress(const int graph_percent, const int display_percent, -		const int proglen) +static void fill_progress(const int percent, const int proglen)  {  	const unsigned int hashlen = proglen - 8; -	const unsigned int hash = graph_percent * hashlen / 100; +	const unsigned int hash = percent * hashlen / 100;  	static unsigned int lasthash = 0, mouth = 0;  	unsigned int i; -	/* printf("\ndebug: proglen: %i\n", proglen); DEBUG*/ - -	if(graph_percent == 0) { +	if(percent == 0) {  		lasthash = 0;  		mouth = 0;  	} @@ -141,10 +135,10 @@ static void fill_progress(const int graph_percent, const int display_percent,  	}  	/* print percent after progress bar */  	if(proglen > 5) { -		printf(" %3d%%", display_percent); +		printf(" %3d%%", percent);  	} -	if(graph_percent == 100) { +	if(percent == 100) {  		printf("\n");  	} else {  		printf("\r"); @@ -157,8 +151,6 @@ static void fill_progress(const int graph_percent, const int display_percent,  /* callback to handle messages/notifications from libalpm transactions */  void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)  { -	char str[LOG_STR_LEN] = ""; -  	switch(event) {  		case PM_TRANS_EVT_CHECKDEPS_START:  		  printf(_("checking dependencies...\n")); @@ -180,10 +172,9 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)  			}  			break;  		case PM_TRANS_EVT_ADD_DONE: -			snprintf(str, LOG_STR_LEN, "installed %s (%s)\n", +			alpm_logaction("installed %s (%s)\n",  			         alpm_pkg_get_name(data1),  			         alpm_pkg_get_version(data1)); -			alpm_logaction(str);  			break;  		case PM_TRANS_EVT_REMOVE_START:  			if(config->noprogressbar) { @@ -191,10 +182,9 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)  			}  			break;  		case PM_TRANS_EVT_REMOVE_DONE: -			snprintf(str, LOG_STR_LEN, "removed %s (%s)\n", +			alpm_logaction("removed %s (%s)\n",  			         alpm_pkg_get_name(data1),  			         alpm_pkg_get_version(data1)); -			alpm_logaction(str);  			break;  		case PM_TRANS_EVT_UPGRADE_START:  			if(config->noprogressbar) { @@ -202,11 +192,10 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)  			}  			break;  		case PM_TRANS_EVT_UPGRADE_DONE: -			snprintf(str, LOG_STR_LEN, "upgraded %s (%s -> %s)\n", +			alpm_logaction("upgraded %s (%s -> %s)\n",  			         (char *)alpm_pkg_get_name(data1),  			         (char *)alpm_pkg_get_version(data2),  			         (char *)alpm_pkg_get_version(data1)); -			alpm_logaction(str);  			break;  		case PM_TRANS_EVT_INTEGRITY_START:  			printf(_("checking package integrity...\n")); @@ -255,67 +244,46 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)  void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,                     void *data3, int *response)  { -	char str[LOG_STR_LEN] = ""; -  	switch(event) {  		case PM_TRANS_CONV_INSTALL_IGNOREPKG:  			if(data2) {  				/* TODO we take this route based on data2 being not null? WTF */ -				snprintf(str, LOG_STR_LEN, _(":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway? [Y/n] "), +				*response = yesno(1, _(":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway?"),  						alpm_pkg_get_name(data1),  						alpm_pkg_get_name(data2)); -				*response = yesno(str);  			} else { -				snprintf(str, LOG_STR_LEN, _(":: %s is in IgnorePkg/IgnoreGroup. Install anyway? [Y/n] "), +				*response = yesno(1, _(":: %s is in IgnorePkg/IgnoreGroup. Install anyway?"),  						alpm_pkg_get_name(data1)); -				*response = yesno(str);  			}  			break;  		case PM_TRANS_CONV_REMOVE_HOLDPKG: -			snprintf(str, LOG_STR_LEN, _(":: %s is designated as a HoldPkg. Remove anyway? [Y/n] "), +			*response = yesno(1, _(":: %s is designated as a HoldPkg. Remove anyway?"),  					alpm_pkg_get_name(data1)); -			*response = yesno(str);  			break;  		case PM_TRANS_CONV_REPLACE_PKG: -			if(!config->noconfirm) { -				snprintf(str, LOG_STR_LEN, _(":: Replace %s with %s/%s? [Y/n] "), -						alpm_pkg_get_name(data1), -						(char *)data3, -						alpm_pkg_get_name(data2)); -				*response = yesno(str); -			} else { -				printf(_("Replacing %s with %s/%s\n"), -						alpm_pkg_get_name(data1), -						(char *)data3, -						alpm_pkg_get_name(data2)); -				*response = 1; -			} +			*response = yesno(1, _(":: Replace %s with %s/%s?"), +					alpm_pkg_get_name(data1), +					(char *)data3, +					alpm_pkg_get_name(data2));  			break;  		case PM_TRANS_CONV_CONFLICT_PKG: -			snprintf(str, LOG_STR_LEN, _(":: %s conflicts with %s. Remove %s? [Y/n] "), +			*response = yesno(1, _(":: %s conflicts with %s. Remove %s?"),  					(char *)data1,  					(char *)data2,  					(char *)data2); -			*response = yesno(str);  			break;  		case PM_TRANS_CONV_LOCAL_NEWER:  			if(!config->op_s_downloadonly) { -				snprintf(str, LOG_STR_LEN, _(":: %s-%s: local version is newer. Upgrade anyway? [Y/n] "), +				*response = yesno(1, _(":: %s-%s: local version is newer. Upgrade anyway?"),  						alpm_pkg_get_name(data1),  						alpm_pkg_get_version(data1)); -				*response = yesno(str);  			} else {  				*response = 1;  			}  			break;  		case PM_TRANS_CONV_CORRUPTED_PKG: -			if(!config->noconfirm) { -				snprintf(str, LOG_STR_LEN, _(":: File %s is corrupted. Do you want to delete it? [Y/n] "), -						(char *)data1); -				*response = yesno(str); -			} else { -				*response = 1; -			} +			*response = yesno(1, _(":: File %s is corrupted. Do you want to delete it?"), +					(char *)data1);  			break;  	}  } @@ -427,7 +395,7 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,  	free(wcstr);  	/* call refactored fill progress function */ -	fill_progress(percent, percent, getcols() - infolen); +	fill_progress(percent, getcols() - infolen);  	if(percent == 100) {  		alpm_list_t *i = NULL; @@ -443,8 +411,7 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,  }  /* callback to handle display of download progress */ -void cb_dl_progress(const char *filename, int file_xfered, int file_total, -		int list_xfered, int list_total) +void cb_dl_progress(const char *filename, int xfered, int total)  {  	const int infolen = 50;  	const int filenamelen = infolen - 27; @@ -455,43 +422,22 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total,  	float rate = 0.0, timediff = 0.0, f_xfered = 0.0;  	unsigned int eta_h = 0, eta_m = 0, eta_s = 0; -	int graph_percent = 0, display_percent = 0; +	int percent;  	char rate_size = 'K', xfered_size = 'K'; -	int xfered = 0, total = 0; - -	/* Need this variable when TotalDownload is set to know if we should -	 * reset xfered_last and rate_last. */ -	static int has_init = 0;  	if(config->noprogressbar) {  		return;  	} -	/* Choose how to display the amount downloaded, rate, ETA, and -	 * percentage depending on the TotalDownload option. */ -	if (config->totaldownload && list_total > 0) { -		xfered = list_xfered; -		total = list_total; -	} else { -		xfered = file_xfered; -		total = file_total; -	} -  	/* this is basically a switch on file_xferred: 0, file_total, and  	 * anything else */ -	if(file_xfered == 0) { -		/* set default starting values, but only once for TotalDownload */ -		if (!(config->totaldownload && list_total > 0) || -				(config->totaldownload && list_total > 0 && !has_init)) { -			gettimeofday(&initial_time, NULL); -			timediff = get_update_timediff(1); -			xfered_last = 0; -			rate_last = 0.0; -			has_init = 1; -		} -		rate = 0.0; -		eta_s = 0; -	} else if(file_xfered == file_total) { +	if(xfered == 0) { +		/* set default starting values */ +		gettimeofday(&initial_time, NULL); +		xfered_last = 0; +		rate_last = 0.0; +		timediff = get_update_timediff(1); +	} else if(xfered == total) {  		/* compute final values */  		struct timeval current_time;  		float diff_sec, diff_usec; @@ -500,7 +446,7 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total,  		diff_sec = current_time.tv_sec - initial_time.tv_sec;  		diff_usec = current_time.tv_usec - initial_time.tv_usec;  		timediff = diff_sec + (diff_usec / 1000000.0); -		rate = xfered / (timediff * 1024.0); +		rate = total / (timediff * 1024.0);  		/* round elapsed time to the nearest second */  		eta_s = (int)(timediff + 0.5); @@ -514,12 +460,14 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total,  		}  		rate = (xfered - xfered_last) / (timediff * 1024.0);  		/* average rate to reduce jumpiness */ -		rate = (rate + 2*rate_last) / 3; +		rate = (rate + 2 * rate_last) / 3;  		eta_s = (total - xfered) / (rate * 1024.0);  		rate_last = rate;  		xfered_last = xfered;  	} +	percent = (int)((float)xfered) / ((float)total) * 100; +  	/* fix up time for display */  	eta_h = eta_s / 3600;  	eta_s -= eta_h * 3600; @@ -591,11 +539,7 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total,  	free(fname);  	free(wcfname); -	/* The progress bar is based on the file percent regardless of the -	 * TotalDownload option. */ -	graph_percent = (int)((float)file_xfered) / ((float)file_total) * 100; -	display_percent = (int)((float)xfered) / ((float)total) * 100; -	fill_progress(graph_percent, display_percent, getcols() - infolen); +	fill_progress(percent, getcols() - infolen);  	return;  } diff --git a/src/pacman/callback.h b/src/pacman/callback.h index aa8d9370..39d59d8b 100644 --- a/src/pacman/callback.h +++ b/src/pacman/callback.h @@ -33,8 +33,7 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent,                     int howmany, int remain);  /* callback to handle display of download progress */ -void cb_dl_progress(const char *filename, int file_xfered, int file_total, -		int list_xfered, int list_total); +void cb_dl_progress(const char *filename, int file_xfered, int file_total);  /* callback to handle messages/notifications from pacman library */  void cb_log(pmloglevel_t level, char *fmt, va_list args); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index f804f560..28ac4b96 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -27,7 +27,6 @@ typedef struct __config_t {  	unsigned short verbose;  	unsigned short version;  	unsigned short help; -	unsigned short upgrade;  	unsigned short noconfirm;  	unsigned short noprogressbar;  	unsigned short logmask; @@ -53,7 +52,6 @@ typedef struct __config_t {  	unsigned short op_q_upgrade;  	unsigned short op_s_clean; -	unsigned short op_s_dependsonly;  	unsigned short op_s_downloadonly;  	unsigned short op_s_info;  	unsigned short op_s_sync; @@ -67,15 +65,15 @@ typedef struct __config_t {  	unsigned short chomp; /* I Love Candy! */  	unsigned short usecolor; /* enable colorful output */  	unsigned short showsize; /* show individual package sizes */ -	unsigned short totaldownload; /* When downloading, display the amount -	                                 downloaded, rate, ETA, and percent -	                                 downloaded of the total download list */ +	/* When downloading, display the amount downloaded, rate, ETA, and percent +	 * downloaded of the total download list */ +	unsigned short totaldownload; +	unsigned short cleanmethod; /* select -Sc behavior */  } config_t;  /* Operations */  enum {  	PM_OP_MAIN = 1, -	PM_OP_ADD,  	PM_OP_REMOVE,  	PM_OP_UPGRADE,  	PM_OP_QUERY, @@ -83,6 +81,12 @@ enum {  	PM_OP_DEPTEST  }; +/* clean method */ +enum { +	PM_CLEAN_KEEPINST = 0, /* default */ +	PM_CLEAN_KEEPCUR +}; +  /* global config variable */  extern config_t *config; diff --git a/src/pacman/deptest.c b/src/pacman/deptest.c index 2481c0b6..2feca5c4 100644 --- a/src/pacman/deptest.c +++ b/src/pacman/deptest.c @@ -31,53 +31,23 @@  #include "util.h"  #include "conf.h" -/* TODO: This should use _alpm_checkdeps() */  int pacman_deptest(alpm_list_t *targets)  { -	int retval = 0;  	alpm_list_t *i; -	if(targets == NULL) { +	alpm_list_t *deps = alpm_deptest(alpm_option_get_localdb(), targets); +	if(deps == NULL) {  		return(0);  	} -	for(i = targets; i; i = alpm_list_next(i)) { -		int found = 0; -		pmpkg_t *pkg; -		pmdepend_t *dep; -		const char *target; -		alpm_list_t *j, *provides; +	for(i = deps; i; i = alpm_list_next(i)) { +		const char *dep; -		target = alpm_list_getdata(i); -		dep = alpm_splitdep(target); - -		pkg = alpm_db_get_pkg(alpm_option_get_localdb(), -				alpm_dep_get_name(dep)); -		if(pkg && alpm_depcmp(pkg, dep)) { -			found = 1; -		} else { -			/* not found, can we find anything that provides this in the local DB? */ -			provides = alpm_db_whatprovides(alpm_option_get_localdb(), -					alpm_dep_get_name(dep)); -			for(j = provides; j; j = alpm_list_next(j)) { -				pmpkg_t *pkg; -				pkg = alpm_list_getdata(j); - -				if(pkg && alpm_depcmp(pkg, dep)) { -					found = 1; -					break; -				} -			} -			alpm_list_free(provides); -		} - -		if(!found) { -			printf("%s\n", target); -			retval = 127; -		} -		free(dep); +		dep = alpm_list_getdata(i); +		printf("%s\n", dep);  	} -	return(retval); +	alpm_list_free(deps); +	return(127);  }  /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index c2b61fcd..9468d51c 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -68,31 +68,27 @@ static void usage(int op, const char * const myname)  		printf("%s:\n", str_opt);  		printf("    %s {-h --help}\n", myname);  		printf("    %s {-V --version}\n", myname); -		printf("    %s {-A --add}     [%s] <%s>\n", myname, str_opt, str_file);  		printf("    %s {-Q --query}   [%s] [%s]\n", myname, str_opt, str_pkg);  		printf("    %s {-R --remove}  [%s] <%s>\n", myname, str_opt, str_pkg);  		printf("    %s {-S --sync}    [%s] [%s]\n", myname, str_opt, str_pkg);  		printf("    %s {-U --upgrade} [%s] <%s>\n", myname, str_opt, str_file);  		printf(_("\nuse '%s --help' with other options for more syntax\n"), myname);  	} else { -		if(op == PM_OP_ADD) { -			printf("%s:  %s {-A --add} [%s] <%s>\n", str_usg, myname, str_opt, str_file); -			printf("%s:\n", str_opt); -			printf(_("      --asdeps         install packages as non-explicitly installed\n")); -			printf(_("  -d, --nodeps         skip dependency checks\n")); -			printf(_("  -f, --force          force install, overwrite conflicting files\n")); -		} else if(op == PM_OP_REMOVE) { +		if(op == PM_OP_REMOVE) {  			printf("%s:  %s {-R --remove} [%s] <%s>\n", str_usg, myname, str_opt, str_pkg);  			printf("%s:\n", str_opt);  			printf(_("  -c, --cascade        remove packages and all packages that depend on them\n"));  			printf(_("  -d, --nodeps         skip dependency checks\n"));  			printf(_("  -k, --dbonly         only remove database entry, do not remove files\n"));  			printf(_("  -n, --nosave         remove configuration files as well\n")); -			printf(_("  -s, --recursive      remove dependencies also (that won't break packages)\n")); +			printf(_("  -s, --recursive      remove dependencies also (that won't break packages)\n" +				 "                       (-ss includes explicitly installed dependencies too)\n")); +			printf(_("  -u, --unneeded       remove unneeded packages (that won't break packages)\n"));  		} else if(op == PM_OP_UPGRADE) {  			printf("%s:  %s {-U --upgrade} [%s] <%s>\n", str_usg, myname, str_opt, str_file);  			printf("%s:\n", str_opt);  			printf(_("      --asdeps         install packages as non-explicitly installed\n")); +			printf(_("      --asexplicit     install packages as explicitly installed\n"));  			printf(_("  -d, --nodeps         skip dependency checks\n"));  			printf(_("  -f, --force          force install, overwrite conflicting files\n"));  		} else if(op == PM_OP_QUERY) { @@ -115,9 +111,9 @@ static void usage(int op, const char * const myname)  			printf("%s:  %s {-S --sync} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg);  			printf("%s:\n", str_opt);  			printf(_("      --asdeps         install packages as non-explicitly installed\n")); +			printf(_("      --asexplicit     install packages as explicitly installed\n"));  			printf(_("  -c, --clean          remove old packages from cache directory (-cc for all)\n"));  			printf(_("  -d, --nodeps         skip dependency checks\n")); -			printf(_("  -e, --dependsonly    install dependencies only\n"));  			printf(_("  -f, --force          force install, overwrite conflicting files\n"));  			printf(_("  -g, --groups         view all members of a package group\n"));  			printf(_("  -i, --info           view package information\n")); @@ -212,7 +208,7 @@ static void cleanup(int ret) {   * in a consistant state.   * @param signum the thrown signal   */ -static void handler(int signum) +static RETSIGTYPE handler(int signum)  {  	if(signum==SIGSEGV)  	{ @@ -305,7 +301,6 @@ static int parseargs(int argc, char *argv[])  	int option_index = 0;  	static struct option opts[] =  	{ -		{"add",        no_argument,       0, 'A'},  		{"query",      no_argument,       0, 'Q'},  		{"remove",     no_argument,       0, 'R'},  		{"sync",       no_argument,       0, 'S'}, @@ -318,7 +313,6 @@ static int parseargs(int argc, char *argv[])  		{"clean",      no_argument,       0, 'c'},  		{"nodeps",     no_argument,       0, 'd'},  		{"deps",       no_argument,       0, 'd'}, -		{"dependsonly",no_argument,       0, 'e'},  		{"explicit",   no_argument,       0, 'e'},  		{"force",      no_argument,       0, 'f'},  		{"groups",     no_argument,       0, 'g'}, @@ -338,6 +332,7 @@ static int parseargs(int argc, char *argv[])  		{"unrequired", no_argument,       0, 't'},  		{"upgrades",   no_argument,       0, 'u'},  		{"sysupgrade", no_argument,       0, 'u'}, +		{"unneeded",   no_argument,       0, 'u'},  		{"verbose",    no_argument,       0, 'v'},  		{"downloadonly", no_argument,     0, 'w'},  		{"refresh",    no_argument,       0, 'y'}, @@ -352,10 +347,11 @@ static int parseargs(int argc, char *argv[])  		{"logfile",    required_argument, 0, 1009},  		{"ignoregroup", required_argument, 0, 1010},  		{"needed",     no_argument,       0, 1011}, +		{"asexplicit",     no_argument,   0, 1012},  		{0, 0, 0, 0}  	}; -	while((opt = getopt_long(argc, argv, "ARUFQSTr:b:vkhscVfmnoldepqituwygz", opts, &option_index))) { +	while((opt = getopt_long(argc, argv, "RUFQSTr:b:vkhscVfmnoldepqituwygz", opts, &option_index))) {  		alpm_list_t *list = NULL, *item = NULL; /* lists for splitting strings */  		if(opt < 0) { @@ -423,7 +419,9 @@ static int parseargs(int argc, char *argv[])  				FREELIST(list);  				break;  			case 1011: config->flags |= PM_TRANS_FLAG_NEEDED; break; -			case 'A': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_ADD); break; +			case 1012: +				config->flags |= PM_TRANS_FLAG_ALLEXPLICIT; +				break;  			case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break;  			case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break;  			case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break; @@ -444,7 +442,6 @@ static int parseargs(int argc, char *argv[])  				break;  			case 'e':  				config->op_q_explicit = 1; -				config->flags |= PM_TRANS_FLAG_DEPENDSONLY;  				break;  			case 'f': config->flags |= PM_TRANS_FLAG_FORCE; break;  			case 'g': (config->group)++; break; @@ -468,7 +465,11 @@ static int parseargs(int argc, char *argv[])  			case 's':  				config->op_s_search = 1;  				config->op_q_search = 1; -				config->flags |= PM_TRANS_FLAG_RECURSE; +				if(config->flags & PM_TRANS_FLAG_RECURSE) { +					config->flags |= PM_TRANS_FLAG_RECURSEALL; +				} else { +					config->flags |= PM_TRANS_FLAG_RECURSE; +				}  				break;  			case 't':  				config->op_q_unrequired = 1; @@ -476,6 +477,7 @@ static int parseargs(int argc, char *argv[])  			case 'u':  				config->op_s_upgrade = 1;  				config->op_q_upgrade = 1; +				config->flags |= PM_TRANS_FLAG_UNNEEDED;  				break;  			case 'v': (config->verbose)++; break;  			case 'w': @@ -599,7 +601,7 @@ static int _parseconfig(const char *file, const char *givensection,  			}  		} else {  			/* directive */ -			char *key, *upperkey; +			char *key;  			/* strsep modifies the 'line' string: 'key \0 ptr' */  			key = line;  			ptr = line; @@ -612,11 +614,7 @@ static int _parseconfig(const char *file, const char *givensection,  						file, linenum);  				return(1);  			} -			/* For each directive, compare to the uppercase and camelcase string. -			 * This prevents issues with certain locales where characters don't -			 * follow the toupper() rules we may expect, e.g. tr_TR where i != I. -			 */ -			upperkey = strtoupper(strdup(key)); +			/* For each directive, compare to the camelcase string. */  			if(section == NULL) {  				pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"),  						file, linenum); @@ -624,25 +622,25 @@ static int _parseconfig(const char *file, const char *givensection,  			}  			if(ptr == NULL && strcmp(section, "options") == 0) {  				/* directives without settings, all in [options] */ -				if(strcmp(key, "NoPassiveFTP") == 0 || strcmp(upperkey, "NOPASSIVEFTP") == 0) { +				if(strcmp(key, "NoPassiveFTP") == 0) {  					alpm_option_set_nopassiveftp(1);  					pm_printf(PM_LOG_DEBUG, "config: nopassiveftp\n"); -				} else if(strcmp(key, "UseSyslog") == 0 || strcmp(upperkey, "USESYSLOG") == 0) { +				} else if(strcmp(key, "UseSyslog") == 0) {  					alpm_option_set_usesyslog(1);  					pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); -				} else if(strcmp(key, "ILoveCandy") == 0 || strcmp(upperkey, "ILOVECANDY") == 0) { +				} else if(strcmp(key, "ILoveCandy") == 0) {  					config->chomp = 1;  					pm_printf(PM_LOG_DEBUG, "config: chomp\n"); -				} else if(strcmp(key, "UseColor") == 0 || strcmp(upperkey, "USECOLOR") == 0) { +				} else if(strcmp(key, "UseColor") == 0) {  					config->usecolor = 1;  					pm_printf(PM_LOG_DEBUG, "config: usecolor\n"); -				} else if(strcmp(key, "ShowSize") == 0 || strcmp(upperkey, "SHOWSIZE") == 0) { +				} else if(strcmp(key, "ShowSize") == 0) {  					config->showsize = 1;  					pm_printf(PM_LOG_DEBUG, "config: showsize\n"); -				} else if(strcmp(key, "UseDelta") == 0 || strcmp(upperkey, "USEDELTA") == 0) { +				} else if(strcmp(key, "UseDelta") == 0) {  					alpm_option_set_usedelta(1);  					pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); -				} else if(strcmp(key, "TotalDownload") == 0 || strcmp(upperkey, "TOTALDOWNLOAD") == 0) { +				} else if(strcmp(key, "TotalDownload") == 0) {  					config->totaldownload = 1;  					pm_printf(PM_LOG_DEBUG, "config: totaldownload\n");  				} else { @@ -652,59 +650,64 @@ static int _parseconfig(const char *file, const char *givensection,  				}  			} else {  				/* directives with settings */ -				if(strcmp(key, "Include") == 0 || strcmp(upperkey, "INCLUDE") == 0) { +				if(strcmp(key, "Include") == 0) {  					pm_printf(PM_LOG_DEBUG, "config: including %s\n", ptr);  					_parseconfig(ptr, section, db);  					/* Ignore include failures... assume non-critical */  				} else if(strcmp(section, "options") == 0) { -					if(strcmp(key, "NoUpgrade") == 0 -							|| strcmp(upperkey, "NOUPGRADE") == 0) { +					if(strcmp(key, "NoUpgrade") == 0) {  						setrepeatingoption(ptr, "NoUpgrade", alpm_option_add_noupgrade); -					} else if(strcmp(key, "NoExtract") == 0 -							|| strcmp(upperkey, "NOEXTRACT") == 0) { +					} else if(strcmp(key, "NoExtract") == 0) {  						setrepeatingoption(ptr, "NoExtract", alpm_option_add_noextract); -					} else if(strcmp(key, "IgnorePkg") == 0 -							|| strcmp(upperkey, "IGNOREPKG") == 0) { +					} else if(strcmp(key, "IgnorePkg") == 0) {  						setrepeatingoption(ptr, "IgnorePkg", alpm_option_add_ignorepkg); -					} else if(strcmp(key, "IgnoreGroup") == 0 -							|| strcmp(upperkey, "IGNOREGROUP") == 0) { +					} else if(strcmp(key, "IgnoreGroup") == 0) {  						setrepeatingoption(ptr, "IgnoreGroup", alpm_option_add_ignoregrp); -					} else if(strcmp(key, "HoldPkg") == 0 -							|| strcmp(upperkey, "HOLDPKG") == 0) { +					} else if(strcmp(key, "HoldPkg") == 0) {  						setrepeatingoption(ptr, "HoldPkg", alpm_option_add_holdpkg); -					} else if(strcmp(key, "DBPath") == 0 || strcmp(upperkey, "DBPATH") == 0) { +					} else if(strcmp(key, "DBPath") == 0) {  						/* don't overwrite a path specified on the command line */  						if(!config->dbpath) {  							config->dbpath = strdup(ptr);  							pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", ptr);  						} -					} else if(strcmp(key, "CacheDir") == 0 || strcmp(upperkey, "CACHEDIR") == 0) { +					} else if(strcmp(key, "CacheDir") == 0) {  						if(alpm_option_add_cachedir(ptr) != 0) {  							pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"),  									ptr, alpm_strerrorlast());  							return(1);  						}  						pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", ptr); -					} else if(strcmp(key, "RootDir") == 0 || strcmp(upperkey, "ROOTDIR") == 0) { +					} else if(strcmp(key, "RootDir") == 0) {  						/* don't overwrite a path specified on the command line */  						if(!config->rootdir) {  							config->rootdir = strdup(ptr);  							pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", ptr);  						} -					} else if (strcmp(key, "LogFile") == 0 || strcmp(upperkey, "LOGFILE") == 0) { +					} else if (strcmp(key, "LogFile") == 0) {  						if(!config->logfile) {  							config->logfile = strdup(ptr);  							pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", ptr);  						} -					} else if (strcmp(key, "XferCommand") == 0 || strcmp(upperkey, "XFERCOMMAND") == 0) { +					} else if (strcmp(key, "XferCommand") == 0) {  						alpm_option_set_xfercommand(ptr);  						pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", ptr); +					} else if (strcmp(key, "CleanMethod") == 0) { +						if (strcmp(ptr, "KeepInstalled") == 0) { +							config->cleanmethod = PM_CLEAN_KEEPINST; +						} else if (strcmp(ptr, "KeepCurrent") == 0) { +							config->cleanmethod = PM_CLEAN_KEEPCUR; +						} else { +							pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), ptr); +							return(1); +						} +						pm_printf(PM_LOG_DEBUG, "config: cleanmethod: %s\n", ptr);  					} else {  						pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),  								file, linenum, key);  						return(1);  					} -				} else if(strcmp(key, "Server") == 0 || strcmp(upperkey, "SERVER") == 0) { +				} else if(strcmp(key, "Server") == 0) {  					/* let's attempt a replacement for the current repo */  					char *server = strreplace(ptr, "$repo", section); @@ -720,7 +723,6 @@ static int _parseconfig(const char *file, const char *givensection,  					return(1);  				}  			} -			free(upperkey);  		}  	}  	fclose(fp); @@ -867,9 +869,6 @@ int main(int argc, char *argv[])  	/* start the requested operation */  	switch(config->op) { -		case PM_OP_ADD: -			ret = pacman_add(pm_targets); -			break;  		case PM_OP_REMOVE:  			ret = pacman_remove(pm_targets);  			break; diff --git a/src/pacman/pacman.h b/src/pacman/pacman.h index 9d23a89c..97d0301e 100644 --- a/src/pacman/pacman.h +++ b/src/pacman/pacman.h @@ -21,15 +21,14 @@  #include <alpm_list.h> -/* add.c, this should merge with upgrade.c */ -int pacman_add(alpm_list_t *targets); -int pacman_upgrade(alpm_list_t *targets); -/* sync.c */ -int pacman_sync(alpm_list_t *targets);  /* query.c */  int pacman_query(alpm_list_t *targets);  /* remove.c */  int pacman_remove(alpm_list_t *targets); +/* sync.c */ +int pacman_sync(alpm_list_t *targets); +/* upgrade.c */ +int pacman_upgrade(alpm_list_t *targets);  /* deptest.c */  int pacman_deptest(alpm_list_t *targets); diff --git a/src/pacman/query.c b/src/pacman/query.c index e999a328..b40359ed 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -1,7 +1,7 @@  /*   *  query.c   * - *  Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> + *  Copyright (c) 2002-2008 by Judd Vinet <jvinet@zeroflux.org>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License as published by @@ -119,8 +119,13 @@ static int query_fileowner(alpm_list_t *targets)  				free(pdname);  				if(ppath && strcmp(ppath, rpath) == 0) { -					printf(_("%s is owned by %s %s\n"), filename, -					       alpm_pkg_get_name(info), alpm_pkg_get_version(info)); +					if (!config->quiet) { +						printf(_("%s is owned by %s %s\n"), filename, +								alpm_pkg_get_name(info), alpm_pkg_get_version(info)); +					} else { +						printf("%s %s\n", alpm_pkg_get_name(info), +								alpm_pkg_get_version(info)); +					}  					found = 1;  				}  				free(ppath); @@ -155,7 +160,6 @@ static int query_search(alpm_list_t *targets)  	}  	for(i = searchlist; i; i = alpm_list_next(i)) { -		char *group = NULL;  		alpm_list_t *grp;  		pmpkg_t *pkg = alpm_list_getdata(i); @@ -176,8 +180,17 @@ static int query_search(alpm_list_t *targets)  		if (!config->quiet) {  			if((grp = alpm_pkg_get_groups(pkg)) != NULL) { -				group = alpm_list_getdata(grp); -				printf(" (%s)", (char *)alpm_list_getdata(grp)); +				alpm_list_t *k; +				printf(" ("); +				for(k = grp; k; k = alpm_list_next(k)) { +					const char *group = alpm_list_getdata(k); +					printf("%s", group); +					if(alpm_list_next(k)) { +						/* only print a spacer if there are more groups */ +						printf(" "); +					} +				} +				printf(")");  			}  			/* we need a newline and initial indent first */ @@ -197,33 +210,33 @@ static int query_search(alpm_list_t *targets)  static int query_group(alpm_list_t *targets)  {  	alpm_list_t *i, *j; -	char *package = NULL; +	char *grpname = NULL;  	int ret = 0;  	if(targets == NULL) {  		for(j = alpm_db_getgrpcache(db_local); j; j = alpm_list_next(j)) {  			pmgrp_t *grp = alpm_list_getdata(j); -			const alpm_list_t *p, *pkgnames; +			const alpm_list_t *p, *packages;  			const char *grpname;  			grpname = alpm_grp_get_name(grp); -			pkgnames = alpm_grp_get_pkgs(grp); +			packages = alpm_grp_get_pkgs(grp); -			for(p = pkgnames; p; p = alpm_list_next(p)) { -				printf("%s %s\n", grpname, (char *)alpm_list_getdata(p)); +			for(p = packages; p; p = alpm_list_next(p)) { +				printf("%s %s\n", grpname, alpm_pkg_get_name(alpm_list_getdata(p)));  			}  		}  	} else {  		for(i = targets; i; i = alpm_list_next(i)) {  			pmgrp_t *grp; -			package = alpm_list_getdata(i); -			grp = alpm_db_readgrp(db_local, package); +			grpname = alpm_list_getdata(i); +			grp = alpm_db_readgrp(db_local, grpname);  			if(grp) { -				const alpm_list_t *p, *pkgnames = alpm_grp_get_pkgs(grp); -				for(p = pkgnames; p; p = alpm_list_next(p)) { -					printf("%s %s\n", package, (char *)alpm_list_getdata(p)); +				const alpm_list_t *p, *packages = alpm_grp_get_pkgs(grp); +				for(p = packages; p; p = alpm_list_next(p)) { +					printf("%s %s\n", grpname, alpm_pkg_get_name(alpm_list_getdata(p)));  				}  			} else { -				fprintf(stderr, _("error: group \"%s\" was not found\n"), package); +				fprintf(stderr, _("error: group \"%s\" was not found\n"), grpname);  				ret++;  			}  		} diff --git a/src/pacman/remove.c b/src/pacman/remove.c index e3750e4c..a2209ac6 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -29,24 +29,10 @@  /* pacman */  #include "pacman.h"  #include "util.h" -#include "callback.h"  #include "conf.h"  extern pmdb_t *db_local; -/* Free the current transaction and print an error if unsuccessful */ -static int remove_cleanup(void) -{ -	int ret = alpm_trans_release(); -	if(ret != 0) { -		pm_printf(PM_LOG_ERROR, _("failed to release transaction (%s)\n"), -		        alpm_strerrorlast()); -		ret = 1; -	} - -	return(ret); -} -  /**   * @brief Remove a specified list of packages.   * @@ -75,11 +61,11 @@ int pacman_remove(alpm_list_t *targets)  			printf(_(":: group %s:\n"), alpm_grp_get_name(grp));  			list_display("   ", pkgnames); -			all = yesno(_("    Remove whole content? [Y/n] ")); +			all = yesno(1, _("    Remove whole content?"));  			for(p = pkgnames; p; p = alpm_list_next(p)) {  				char *pkg = alpm_list_getdata(p); -				if(all || yesno(_(":: Remove %s from group %s? [Y/n] "), pkg, (char *)alpm_list_getdata(i))) { +				if(all || yesno(1, _(":: Remove %s from group %s?"), pkg, (char *)alpm_list_getdata(i))) {  					finaltargs = alpm_list_add(finaltargs, strdup(pkg));  				}  			} @@ -90,14 +76,7 @@ int pacman_remove(alpm_list_t *targets)  	}  	/* Step 1: create a new transaction */ -	if(alpm_trans_init(PM_TRANS_TYPE_REMOVE, config->flags, -	   cb_trans_evt, cb_trans_conv, cb_trans_progress) == -1) { -		fprintf(stderr, _("error: failed to init transaction (%s)\n"), -		        alpm_strerrorlast()); -		if(pm_errno == PM_ERR_HANDLE_LOCK) { -			printf(_("  if you're sure a package manager is not already\n" -			         "  running, you can remove %s.\n"), alpm_option_get_lockfile()); -		} +	if(trans_init(PM_TRANS_TYPE_REMOVE, config->flags) == -1) {  		FREELIST(finaltargs);  		return(1);  	} @@ -109,7 +88,7 @@ int pacman_remove(alpm_list_t *targets)  		if(alpm_trans_addtarget(targ) == -1) {  			fprintf(stderr, _("error: '%s': %s\n"),  					targ, alpm_strerrorlast()); -			remove_cleanup(); +			trans_release();  			FREELIST(finaltargs);  			return(1);  		} @@ -134,7 +113,7 @@ int pacman_remove(alpm_list_t *targets)  			default:  				break;  		} -		remove_cleanup(); +		trans_release();  		FREELIST(finaltargs);  		return(1);  	} @@ -153,8 +132,8 @@ int pacman_remove(alpm_list_t *targets)  		list_display(_("Targets:"), lst);  		FREELIST(lst);  		/* get confirmation */ -		if(yesno(_("\nDo you want to remove these packages? [Y/n] ")) == 0) { -			remove_cleanup(); +		if(yesno(1, _("\nDo you want to remove these packages?")) == 0) { +			trans_release();  			FREELIST(finaltargs);  			return(1);  		} @@ -165,13 +144,15 @@ int pacman_remove(alpm_list_t *targets)  	if(alpm_trans_commit(NULL) == -1) {  		fprintf(stderr, _("error: failed to commit transaction (%s)\n"),  		        alpm_strerrorlast()); -		remove_cleanup(); +		trans_release();  		FREELIST(finaltargs);  		return(1);  	}  	/* Step 4: release transaction resources */ -	retval = remove_cleanup(); +	if(trans_release() == -1) { +		retval = 1; +	}  	FREELIST(finaltargs);  	return(retval);  } diff --git a/src/pacman/sync.c b/src/pacman/sync.c index e3e87703..77b66da5 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -29,15 +29,11 @@  #include <alpm.h>  #include <alpm_list.h> -#include <download.h> /* downloadLastErrString */ -/* TODO remove above download.h inclusion once we abstract more, and also - * remove it from Makefile.am on the pacman side */  /* pacman */  #include "pacman.h"  #include "util.h"  #include "package.h" -#include "callback.h"  #include "conf.h"  extern pmdb_t *db_local; @@ -89,7 +85,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) {  		/* We have a directory that doesn't match any syncdb.  		 * Ask the user if he wants to remove it. */  		if(!found) { -			if(!yesno(_("Do you want to remove %s? [Y/n] "), path)) { +			if(!yesno(1, _("Do you want to remove %s?"), path)) {  				continue;  			} @@ -108,7 +104,7 @@ static int sync_cleandb_all(void) {  	char newdbpath[PATH_MAX];  	printf(_("Database directory: %s\n"), dbpath); -	if(!yesno(_("Do you want to remove unused repositories? [Y/n] "))) { +	if(!yesno(1, _("Do you want to remove unused repositories?"))) {  		return(0);  	}  	/* The sync dbs were previously put in dbpath/, but are now in dbpath/sync/, @@ -133,13 +129,23 @@ static int sync_cleancache(int level)  		/* incomplete cleanup */  		DIR *dir;  		struct dirent *ent; -		/* Let's vastly improve the way this is done. Before, we went by package -		 * name. Instead, let's only keep packages we have installed. Open up each -		 * package and see if it has an entry in the local DB; if not, delete it. -		 */ +		/* Open up each package and see if it should be deleted, +		 * depending on the clean method used */  		printf(_("Cache directory: %s\n"), cachedir); -		if(!yesno(_("Do you want to remove uninstalled packages from cache? [Y/n] "))) { -			return(0); +		switch(config->cleanmethod) { +			case PM_CLEAN_KEEPINST: +				if(!yesno(1, _("Do you want to remove uninstalled packages from cache?"))) { +					return(0); +				} +				break; +			case PM_CLEAN_KEEPCUR: +				if(!yesno(1, _("Do you want to remove outdated packages from cache?"))) { +					return(0); +				} +				break; +			default: +				/* this should not happen : the config parsing doesn't set any other value */ +				return(1);  		}  		printf(_("removing old packages from cache... ")); @@ -153,13 +159,16 @@ static int sync_cleancache(int level)  		/* step through the directory one file at a time */  		while((ent = readdir(dir)) != NULL) {  			char path[PATH_MAX]; -			pmpkg_t *localpkg = NULL, *dbpkg = NULL; +			int delete = 1; +			pmpkg_t *localpkg = NULL, *pkg = NULL; +			alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); +			alpm_list_t *j;  			if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {  				continue;  			}  			/* build the full filepath */ -			snprintf(path, PATH_MAX, "%s/%s", cachedir, ent->d_name); +			snprintf(path, PATH_MAX, "%s%s", cachedir, ent->d_name);  			/* attempt to load the package, skip file on failures as we may have  			 * files here that aren't valid packages. we also don't need a full @@ -167,25 +176,45 @@ static int sync_cleancache(int level)  			if(alpm_pkg_load(path, 0, &localpkg) != 0 || localpkg == NULL) {  				continue;  			} -			/* check if this package is in the local DB */ -			dbpkg = alpm_db_get_pkg(db_local, alpm_pkg_get_name(localpkg)); -			if(dbpkg == NULL) { -				/* delete package, not present in local DB */ -				unlink(path); -			} else if(alpm_pkg_vercmp(alpm_pkg_get_version(localpkg), -							alpm_pkg_get_version(dbpkg)) != 0) { -				/* delete package, it was found but version differs */ -				unlink(path); +			switch(config->cleanmethod) { +				case PM_CLEAN_KEEPINST: +					/* check if this package is in the local DB */ +					pkg = alpm_db_get_pkg(db_local, alpm_pkg_get_name(localpkg)); +					if(pkg != NULL && alpm_pkg_vercmp(alpm_pkg_get_version(localpkg), +								alpm_pkg_get_version(pkg)) == 0) { +						/* package was found in local DB and version matches, keep it */ +						delete = 0; +					} +					break; +				case PM_CLEAN_KEEPCUR: +					/* check if this package is in a sync DB */ +					for(j = sync_dbs; j && delete; j = alpm_list_next(j)) { +						pmdb_t *db = alpm_list_getdata(j); +						pkg = alpm_db_get_pkg(db, alpm_pkg_get_name(localpkg)); +						if(pkg != NULL && alpm_pkg_vercmp(alpm_pkg_get_version(localpkg), +									alpm_pkg_get_version(pkg)) == 0) { +							/* package was found in a sync DB and version matches, keep it */ +							delete = 0; +						} +					} +					break; +				default: +					/* this should not happen : the config parsing doesn't set any other value */ +					delete = 0; +					break;  			} -			/* else version was the same, so keep the package */  			/* free the local file package */  			alpm_pkg_free(localpkg); + +			if(delete) { +				unlink(path); +			}  		}  		printf(_("done.\n"));  	} else {  		/* full cleanup */  		printf(_("Cache directory: %s\n"), cachedir); -		if(!yesno(_("Do you want to remove ALL packages from cache? [Y/n] "))) { +		if(!yesno(0, _("Do you want to remove ALL packages from cache?"))) {  			return(0);  		}  		printf(_("removing all packages from cache... ")); @@ -205,52 +234,22 @@ static int sync_cleancache(int level)  	return(0);  } -static int sync_trans_init(pmtransflag_t flags) { -	if(alpm_trans_init(PM_TRANS_TYPE_SYNC, flags, cb_trans_evt, -				cb_trans_conv, cb_trans_progress) == -1) { -		fprintf(stderr, _("error: failed to init transaction (%s)\n"), -				alpm_strerrorlast()); -		if(pm_errno == PM_ERR_HANDLE_LOCK) { -			printf(_("  if you're sure a package manager is not already\n" -						"  running, you can remove %s.\n"), alpm_option_get_lockfile()); -		} -		return(-1); -	} -	return(0); -} - -static int sync_trans_release() { -	if(alpm_trans_release() == -1) { -		fprintf(stderr, _("error: failed to release transaction (%s)\n"), -				alpm_strerrorlast()); -		return(-1); -	} -	return(0); -}  static int sync_synctree(int level, alpm_list_t *syncs)  {  	alpm_list_t *i;  	int success = 0, ret; +	if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) { +		return(0); +	} +  	for(i = syncs; i; i = alpm_list_next(i)) {  		pmdb_t *db = alpm_list_getdata(i);  		ret = alpm_db_update((level < 2 ? 0 : 1), db);  		if(ret < 0) { -			if(pm_errno == PM_ERR_DB_SYNC) { -				/* use libdownload error */ -				/* TODO breaking abstraction barrier here? -				 *			pacman -> libalpm -> libdownload -				 * -				 * Yes.  This will be here until we add a nice pacman "pm_errstr" or -				 * something, OR add all libdownload error codes into the pm_error enum -				 */ -				fprintf(stderr, _("error: failed to synchronize %s: %s\n"), -				        alpm_db_get_name(db), downloadLastErrString); -			} else { -				fprintf(stderr, _("error: failed to update %s (%s)\n"), -				        alpm_db_get_name(db), alpm_strerrorlast()); -			} +			fprintf(stderr, _("error: failed to update %s (%s)\n"), +					alpm_db_get_name(db), alpm_strerrorlast());  		} else if(ret == 1) {  			printf(_(" %s is up to date\n"), alpm_db_get_name(db));  			success++; @@ -259,10 +258,16 @@ static int sync_synctree(int level, alpm_list_t *syncs)  		}  	} +	if(trans_release() == -1) { +		return(0); +	}  	/* We should always succeed if at least one DB was upgraded - we may possibly  	 * fail later with unresolved deps, but that should be rare, and would be  	 * expected  	 */ +	if(!success) { +		fprintf(stderr, _("error: failed to synchronize any databases\n")); +	}  	return(success > 0);  } @@ -289,8 +294,6 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets)  			found = 1;  		}  		for(j = ret; j; j = alpm_list_next(j)) { -			/* print repo/name (group) info about each package in our list */ -			char *group = NULL;  			alpm_list_t *grp;  			pmpkg_t *pkg = alpm_list_getdata(j); @@ -311,8 +314,17 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets)  			if (!config->quiet) {  				if((grp = alpm_pkg_get_groups(pkg)) != NULL) { -					group = alpm_list_getdata(grp); -					printf(" (%s)", (char *)alpm_list_getdata(grp)); +					alpm_list_t *k; +					printf(" ("); +					for(k = grp; k; k = alpm_list_next(k)) { +						const char *group = alpm_list_getdata(k); +						printf("%s", group); +						if(alpm_list_next(k)) { +							/* only print a spacer if there are more groups */ +							printf(" "); +						} +					} +					printf(")");  				}  				/* we need a newline and initial indent first */ @@ -332,7 +344,8 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets)  static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets)  { -	alpm_list_t *i, *j; +	alpm_list_t *i, *j, *k; +	alpm_list_t *pkgnames = NULL;  	if(targets) {  		for(i = targets; i; i = alpm_list_next(i)) { @@ -342,9 +355,14 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets)  				pmgrp_t *grp = alpm_db_readgrp(db, grpname);  				if(grp) { -					/* TODO this should be a lot cleaner, why two outputs? */  					printf("%s\n", (char *)alpm_grp_get_name(grp)); -					list_display("   ", alpm_grp_get_pkgs(grp)); +					/* get names of packages in group */ +					for(k = alpm_grp_get_pkgs(grp); k; k = alpm_list_next(k)) { +						pkgnames = alpm_list_add(pkgnames, +								(char*)alpm_pkg_get_name(k->data)); +					} +					list_display("   ", pkgnames); +					alpm_list_free(pkgnames);  				}  			}  		} @@ -357,7 +375,12 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets)  				printf("%s\n", (char *)alpm_grp_get_name(grp));  				if(grp && level > 1) { -					list_display("   ", alpm_grp_get_pkgs(grp)); +					for(k = alpm_grp_get_pkgs(grp); k; k = alpm_list_next(k)) { +						pkgnames = alpm_list_add(pkgnames, +								(char*)alpm_pkg_get_name(k->data)); +					} +					list_display("   ", pkgnames); +					alpm_list_free(pkgnames);  				}  			}  		} @@ -499,34 +522,19 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets)  	return(0);  } -static int sync_trans(alpm_list_t *targets, int sync_only) +static int sync_trans(alpm_list_t *targets)  {  	int retval = 0;  	alpm_list_t *data = NULL;  	alpm_list_t *sync_dbs = alpm_option_get_syncdbs();  	/* Step 1: create a new transaction... */ -	if(sync_trans_init(config->flags) == -1) { +	if(trans_init(PM_TRANS_TYPE_SYNC, config->flags) == -1) {  		return(1);  	} -	if(config->op_s_sync) { -		/* grab a fresh package list */ -		printf(_(":: Synchronizing package databases...\n")); -		alpm_logaction("synchronizing package lists\n"); -		if(!sync_synctree(config->op_s_sync, sync_dbs)) { -			fprintf(stderr, _("error: failed to synchronize any databases\n")); -			retval = 1; -			goto cleanup; -		} -		if(sync_only) { -			goto cleanup; -		} -	} -  	if(config->op_s_upgrade) {  		alpm_list_t *pkgs, *i; -  		printf(_(":: Starting full system upgrade...\n"));  		alpm_logaction("starting full system upgrade\n");  		if(alpm_trans_sysupgrade() == -1) { @@ -550,12 +558,12 @@ static int sync_trans(alpm_list_t *targets, int sync_only)  				if(strcmp("pacman", alpm_pkg_get_name(spkg)) == 0) {  					printf("\n");  					printf(_(":: pacman has detected a newer version of itself.\n")); -					if(yesno(_(":: Do you want to cancel the current operation\n" -					           ":: and install the new pacman version now? [Y/n] "))) { -						if(sync_trans_release() == -1) { +					if(yesno(1, _(":: Do you want to cancel the current operation\n" +					           ":: and install the new pacman version now?"))) { +						if(trans_release() == -1) {  							return(1);  						} -						if(sync_trans_init(0) == -1) { +						if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) {  							return(1);  						}  						if(alpm_trans_addtarget("pacman") == -1) { @@ -594,26 +602,31 @@ static int sync_trans(alpm_list_t *targets, int sync_only)  					pmdb_t *db = alpm_list_getdata(j);  					grp = alpm_db_readgrp(db, targ);  					if(grp) { -						alpm_list_t *k; +						alpm_list_t *k, *pkgnames = NULL;  						found++;  						printf(_(":: group %s (including ignored packages):\n"), targ);  						/* remove dupe entries in case a package exists in multiple repos */ -						const alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp); +						alpm_list_t *grppkgs = alpm_grp_get_pkgs(grp);  						alpm_list_t *pkgs = alpm_list_remove_dupes(grppkgs); -						list_display("   ", pkgs); -						if(yesno(_(":: Install whole content? [Y/n] "))) { -							for(k = pkgs; k; k = alpm_list_next(k)) { +						for(k = pkgs; k; k = alpm_list_next(k)) { +							pkgnames = alpm_list_add(pkgnames, +									(char*)alpm_pkg_get_name(k->data)); +						} +						list_display("   ", pkgnames); +						if(yesno(1, _(":: Install whole content?"))) { +							for(k = pkgnames; k; k = alpm_list_next(k)) {  								targets = alpm_list_add(targets, strdup(alpm_list_getdata(k)));  							}  						} else { -							for(k = pkgs; k; k = alpm_list_next(k)) { +							for(k = pkgnames; k; k = alpm_list_next(k)) {  								char *pkgname = alpm_list_getdata(k); -								if(yesno(_(":: Install %s from group %s? [Y/n] "), pkgname, targ)) { +								if(yesno(1, _(":: Install %s from group %s?"), pkgname, targ)) {  									targets = alpm_list_add(targets, strdup(pkgname));  								}  							}  						} +						alpm_list_free(pkgnames);  						alpm_list_free(pkgs);  					}  				} @@ -698,19 +711,9 @@ static int sync_trans(alpm_list_t *targets, int sync_only)  		printf("\n");  		if(config->op_s_downloadonly) { -			if(config->noconfirm) { -				printf(_("Beginning download...\n")); -				confirm = 1; -			} else { -				confirm = yesno(_("Proceed with download? [Y/n] ")); -			} +			confirm = yesno(1, _("Proceed with download?"));  		} else { -			if(config->noconfirm) { -				printf(_("Beginning upgrade process...\n")); -				confirm = 1; -			} else { -				confirm = yesno(_("Proceed with installation? [Y/n] ")); -			} +			confirm = yesno(1, _("Proceed with installation?"));  		}  		if(!confirm) {  			goto cleanup; @@ -741,9 +744,11 @@ static int sync_trans(alpm_list_t *targets, int sync_only)  					}  				}  				break; -			case PM_ERR_PKG_CORRUPTED: +			case PM_ERR_PKG_INVALID: +			case PM_ERR_DLT_INVALID:  				for(i = data; i; i = alpm_list_next(i)) { -					printf("%s", (char*)alpm_list_getdata(i)); +					char *filename = alpm_list_getdata(i); +					printf(_("%s is invalid or corrupted\n"), filename);  				}  				break;  			default: @@ -760,7 +765,7 @@ cleanup:  	if(data) {  		FREELIST(data);  	} -	if(sync_trans_release() == -1) { +	if(trans_release() == -1) {  		retval = 1;  	} @@ -770,20 +775,19 @@ cleanup:  int pacman_sync(alpm_list_t *targets)  {  	alpm_list_t *sync_dbs = NULL; -	int sync_only = 0;  	/* clean the cache */  	if(config->op_s_clean) {  		int ret = 0; -		if(sync_trans_init(0) == -1) { +		if(trans_init(PM_TRANS_TYPE_SYNC, 0) == -1) {  			return(1);  		}  		ret += sync_cleancache(config->op_s_clean);  		ret += sync_cleandb_all(); -		if(sync_trans_release() == -1) { +		if(trans_release() == -1) {  			ret++;  		} @@ -797,18 +801,27 @@ int pacman_sync(alpm_list_t *targets)  		return(1);  	} -	if(config->op_s_search || config->group -			|| config->op_s_info || config->op_q_list) { -		sync_only = 1; -	} else if(targets == NULL && !(config->op_s_sync || config->op_s_upgrade)) { +	if(targets == NULL && !(config->op_s_sync || config->op_s_upgrade +				|| config->op_s_search || config->group +				|| config->op_s_info || config->op_q_list)) {  		/* don't proceed here unless we have an operation that doesn't require  		 * a target list */  		pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));  		return(1);  	} +	if(config->op_s_sync) { +		/* grab a fresh package list */ +		printf(_(":: Synchronizing package databases...\n")); +		alpm_logaction("synchronizing package lists\n"); +		if(!sync_synctree(config->op_s_sync, sync_dbs)) { +			return(1); +		} +		config->op_s_sync = 0; +	} +  	if(needs_transaction()) { -		if(sync_trans(targets, sync_only) == 1) { +		if(sync_trans(targets) == 1) {  			return(1);  		}  	} diff --git a/src/pacman/add.c b/src/pacman/upgrade.c index fd40f005..589970ed 100644 --- a/src/pacman/add.c +++ b/src/pacman/upgrade.c @@ -1,5 +1,5 @@  /* - *  add.c + *  upgrade.c   *   *  Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org>   * @@ -28,23 +28,9 @@  /* pacman */  #include "pacman.h" -#include "callback.h"  #include "conf.h"  #include "util.h" -/* Free the current transaction and print an error if unsuccessful */ -static int add_cleanup(void) -{ -	int ret = alpm_trans_release(); -	if(ret != 0) { -		pm_printf(PM_LOG_ERROR, _("failed to release transaction (%s)\n"), -		        alpm_strerrorlast()); -		ret = 1; -	} - -	return(ret); -} -  /**   * @brief Upgrade a specified list of packages.   * @@ -54,23 +40,8 @@ static int add_cleanup(void)   */  int pacman_upgrade(alpm_list_t *targets)  { -	/* this is basically just a remove-then-add process. pacman_add() will */ -	/* handle it */ -	config->upgrade = 1; -	return(pacman_add(targets)); -} - -/** - * @brief Add a specified list of packages which cannot already be installed. - * - * @param targets a list of packages (as strings) to add - * - * @return 0 on success, 1 on failure - */ -int pacman_add(alpm_list_t *targets) -{  	alpm_list_t *i, *data = NULL; -	pmtranstype_t transtype = PM_TRANS_TYPE_ADD; +	pmtranstype_t transtype = PM_TRANS_TYPE_UPGRADE;  	int retval = 0;  	if(targets == NULL) { @@ -93,20 +64,7 @@ int pacman_add(alpm_list_t *targets)  	}  	/* Step 1: create a new transaction */ -	if(config->upgrade == 1) { -		/* if upgrade flag was set, change this to an upgrade transaction */ -		transtype = PM_TRANS_TYPE_UPGRADE; -	} - -	if(alpm_trans_init(transtype, config->flags, cb_trans_evt, -	   cb_trans_conv, cb_trans_progress) == -1) { -		/* TODO: error messages should be in the front end, not the back */ -		fprintf(stderr, _("error: %s\n"), alpm_strerrorlast()); -		if(pm_errno == PM_ERR_HANDLE_LOCK) { -			/* TODO this and the 2 other places should probably be on stderr */ -			printf(_("  if you're sure a package manager is not already\n" -			         "  running, you can remove %s.\n"), alpm_option_get_lockfile()); -		} +	if(trans_init(transtype, config->flags) == -1) {  		return(1);  	} @@ -117,7 +75,7 @@ int pacman_add(alpm_list_t *targets)  		if(alpm_trans_addtarget(targ) == -1) {  			fprintf(stderr, _("error: '%s': %s\n"),  					targ, alpm_strerrorlast()); -			add_cleanup(); +			trans_release();  			return(1);  		}  	} @@ -171,7 +129,7 @@ int pacman_add(alpm_list_t *targets)  			default:  				break;  		} -		add_cleanup(); +		trans_release();  		FREELIST(data);  		return(1);  	} @@ -180,11 +138,13 @@ int pacman_add(alpm_list_t *targets)  	/* Step 3: perform the installation */  	if(alpm_trans_commit(NULL) == -1) {  		fprintf(stderr, _("error: failed to commit transaction (%s)\n"), alpm_strerrorlast()); -		add_cleanup(); +		trans_release();  		return(1);  	} -	retval = add_cleanup(); +	if(trans_release() == -1) { +		retval = 1; +	}  	return(retval);  } diff --git a/src/pacman/util.c b/src/pacman/util.c index 0facfdd1..9617e6f2 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -42,6 +42,33 @@  /* pacman */  #include "util.h"  #include "conf.h" +#include "callback.h" + + +int trans_init(pmtranstype_t type, pmtransflag_t flags) +{ +	if(alpm_trans_init(type, flags, cb_trans_evt, +				cb_trans_conv, cb_trans_progress) == -1) { +		fprintf(stderr, _("error: failed to init transaction (%s)\n"), +				alpm_strerrorlast()); +		if(pm_errno == PM_ERR_HANDLE_LOCK) { +			fprintf(stderr, _("  if you're sure a package manager is not already\n" +						"  running, you can remove %s\n"), alpm_option_get_lockfile()); +		} +		return(-1); +	} +	return(0); +} + +int trans_release() +{ +	if(alpm_trans_release() == -1) { +		fprintf(stderr, _("error: failed to release transaction (%s)\n"), +				alpm_strerrorlast()); +		return(-1); +	} +	return(0); +}  int needs_transaction()  { @@ -234,6 +261,10 @@ void indentprint(const char *str, int indent)  	p = wcstr;  	cidx = indent; +	if(!p) { +		return; +	} +  	while(*p) {  		if(*p == L' ') {  			const wchar_t *q, *next; @@ -464,25 +495,22 @@ void display_targets(const alpm_list_t *syncpkgs, pmdb_t *db_local)  		pmsyncpkg_t *sync = alpm_list_getdata(i);  		pmpkg_t *pkg = alpm_sync_get_pkg(sync); -		/* If this sync record is a replacement, the data member contains -		 * a list of packages to be removed due to the package that is being -		 * installed. */ -		if(alpm_sync_get_type(sync) == PM_SYNC_TYPE_REPLACE) { -			alpm_list_t *to_replace = alpm_sync_get_data(sync); +		/* The removes member contains a list of packages to be removed +		 * due to the package that is being installed. */ +		alpm_list_t *to_replace = alpm_sync_get_removes(sync); -			for(j = to_replace; j; j = alpm_list_next(j)) { -				pmpkg_t *rp = alpm_list_getdata(j); -				const char *name = alpm_pkg_get_name(rp); +		for(j = to_replace; j; j = alpm_list_next(j)) { +			pmpkg_t *rp = alpm_list_getdata(j); +			const char *name = alpm_pkg_get_name(rp); -				if(!alpm_list_find_str(to_remove, name)) { -					rsize += alpm_pkg_get_isize(rp); -					to_remove = alpm_list_add(to_remove, strdup(name)); -				} +			if(!alpm_list_find_str(to_remove, name)) { +				rsize += alpm_pkg_get_isize(rp); +				to_remove = alpm_list_add(to_remove, strdup(name));  			}  		}  		dispsize = alpm_pkg_get_size(pkg); -		dlsize += alpm_pkg_download_size(pkg, db_local); +		dlsize += alpm_pkg_download_size(pkg);  		isize += alpm_pkg_get_isize(pkg);  		/* print the package size with the output if ShowSize option set */ @@ -520,38 +548,50 @@ void display_targets(const alpm_list_t *syncpkgs, pmdb_t *db_local)  	printf("\n");  	printf(_("Total Download Size:    %.2f MB\n"), mbdlsize); - -	/* TODO because all pkgs don't include isize, this is a crude hack */ -	if(mbisize > mbdlsize) { -		printf(_("Total Installed Size:   %.2f MB\n"), mbisize); -	} +	printf(_("Total Installed Size:   %.2f MB\n"), mbisize);  	FREELIST(targets);  }  /* presents a prompt and gets a Y/N answer */ -/* TODO there must be a better way */ -int yesno(char *fmt, ...) +int yesno(short preset, char *fmt, ...)  {  	char response[32];  	va_list args; +	FILE *stream;  	if(config->noconfirm) { -		return(1); +		stream = stdout; +	} else { +		/* Use stderr so questions are always displayed when redirecting output */ +		stream = stderr;  	}  	va_start(args, fmt); -	/* Use stderr so questions are always displayed when redirecting output */ -	vfprintf(stderr, fmt, args); +	vfprintf(stream, fmt, args);  	va_end(args); +	if(preset) { +		fprintf(stream, " %s ", _("[Y/n]")); +	} else { +		fprintf(stream, " %s ", _("[y/N]")); +	} + +	if(config->noconfirm) { +		fprintf(stream, "\n"); +		return(preset); +	} +  	if(fgets(response, 32, stdin)) { -		if(strlen(response) != 0) { -			strtrim(response); +		strtrim(response); +		if(strlen(response) == 0) { +			return(preset);  		} -		if(!strcasecmp(response, _("Y")) || !strcasecmp(response, _("YES")) || strlen(response) == 0) { +		if(!strcasecmp(response, _("Y")) || !strcasecmp(response, _("YES"))) {  			return(1); +		} else if (!strcasecmp(response, _("N")) || !strcasecmp(response, _("NO"))) { +			return(0);  		}  	}  	return(0); diff --git a/src/pacman/util.h b/src/pacman/util.h index 0273512e..722e4ab6 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -36,6 +36,8 @@  /* update speed for the fill_progress based functions */  #define UPDATE_SPEED_SEC 0.2f +int trans_init(pmtranstype_t type, pmtransflag_t flags); +int trans_release();  int needs_transaction();  int getcols();  int makepath(const char *path); @@ -50,7 +52,7 @@ alpm_list_t *strsplit(const char *str, const char splitchar);  void string_display(const char *title, const char *string);  void list_display(const char *title, const alpm_list_t *list);  void display_targets(const alpm_list_t *syncpkgs, pmdb_t *db_local); -int yesno(char *fmt, ...); +int yesno(short preset, char *fmt, ...);  int pm_printf(pmloglevel_t level, const char *format, ...) __attribute__((format(printf,2,3)));  int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...) __attribute__((format(printf,3,4)));  int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list args) __attribute__((format(printf,3,0))); diff --git a/src/util/testdb.c b/src/util/testdb.c index 122a3fb5..f354ecab 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -147,6 +147,14 @@ int main(int argc, char **argv)  		free(depstring);  	} +	/* check conflicts */ +	data = alpm_checkdbconflicts(db); +	for(i = data; i; i = i->next) { +		pmconflict_t *conflict = alpm_list_getdata(i); +		printf("%s conflicts with %s\n", alpm_conflict_get_package1(conflict), +				alpm_conflict_get_package2(conflict)); +	} +  	cleanup(retval);  } diff --git a/src/util/testpkg.c b/src/util/testpkg.c index 64056ce4..6e8f9d1c 100644 --- a/src/util/testpkg.c +++ b/src/util/testpkg.c @@ -63,7 +63,7 @@ int main(int argc, char **argv)  			case PM_ERR_PKG_OPEN:  				printf("Cannot open the given file.\n");  				break; -			case PM_ERR_LIBARCHIVE_ERROR: +			case PM_ERR_LIBARCHIVE:  			case PM_ERR_PKG_INVALID:  				printf("Package is invalid.\n");  				break; | 
