diff options
154 files changed, 5273 insertions, 4924 deletions
diff --git a/Makefile.am b/Makefile.am index dc085429..ea3b0e07 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,12 +11,14 @@ EXTRA_DIST = HACKING pkgdatadir = ${datadir}/${PACKAGE} dist_pkgdata_DATA = PKGBUILD.proto proto.install ChangeLog.proto -# run the pactest test suite -check-local: src/pacman +# run the pactest test suite and vercmp tests +check-local: pactest src/pacman src/util $(PYTHON) $(top_srcdir)/pactest/pactest.py --debug=1 \ --test $(top_srcdir)/pactest/tests/*.py \ -p $(top_builddir)/src/pacman/pacman rm -rf $(top_builddir)/root + $(SH) $(top_srcdir)/pactest/vercmptest.sh \ + $(top_builddir)/src/util/vercmp # create the pacman DB and cache directories upon install install-data-local: diff --git a/PKGBUILD.proto b/PKGBUILD.proto index 9e4b69a0..32655306 100644 --- a/PKGBUILD.proto +++ b/PKGBUILD.proto @@ -29,7 +29,7 @@ build() { ./configure --prefix=/usr make || return 1 - make DESTDIR="$pkgdir" install + make DESTDIR="$pkgdir/" install } # vim:set ts=2 sw=2 et: 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..ab5a3744 100644 --- a/configure.ac +++ b/configure.ac @@ -40,11 +40,6 @@ AC_PREREQ(2.60) # # Bugfix releases: # pacman_version_micro += 1 -# -# pacman_version_suffix should be similar to one of the following: -# For beta releases: [beta2] -# For code under development: [devel] -# For production releases: [] m4_define([lib_current], [5]) m4_define([lib_revision], [1]) @@ -53,16 +48,11 @@ 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], [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_INIT([pacman], [pacman_version], [pacman-dev@archlinux.org]) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) @@ -80,47 +70,58 @@ 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 using git version in pacman version string +AC_ARG_ENABLE(git-version, + AS_HELP_STRING([--enable-git-version], + [enable use of git version in version string if available]), + [wantgitver=$enableval], [wantgitver=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 +130,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 +138,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 +170,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 @@ -242,9 +256,9 @@ fi AM_CONDITIONAL(WANT_DOC, test "x$wantdoc" = "xyes") # Check for doxygen support and status +AC_CHECK_PROGS([DOXYGEN], [doxygen]) AC_MSG_CHECKING([for doxygen]) if test "x$wantdoxygen" = "xyes" ; then - AC_CHECK_PROGS([DOXYGEN], [doxygen]) if test $DOXYGEN ; then AC_MSG_RESULT([yes]) usedoxygen=yes @@ -259,9 +273,9 @@ fi AM_CONDITIONAL(USE_DOXYGEN, test "x$usedoxygen" = "xyes") # Check for asciidoc support and status +AC_CHECK_PROGS([ASCIIDOC], [asciidoc]) AC_MSG_CHECKING([for asciidoc]) if test "x$wantasciidoc" = "xyes" ; then - AC_CHECK_PROGS([ASCIIDOC], [asciidoc]) if test $ASCIIDOC ; then AC_MSG_RESULT([yes]) useasciidoc=yes @@ -291,6 +305,25 @@ else CFLAGS="$CFLAGS -Wall" fi +# Enable or disable use of git version in pacman version string +AC_CHECK_PROGS([GIT], [git]) +AC_CHECK_FILE([.git/], hasgitdir=yes) +AC_MSG_CHECKING(whether to use git version if available) +if test "x$wantgitver" = "xyes" ; then + if test $GIT -a "x$hasgitdir" = "xyes"; then + AC_MSG_RESULT([yes]) + usegitver=yes + AC_DEFINE([USE_GIT_VERSION], , [Use GIT version in version string]) + else + AC_MSG_RESULT([no, git or .git dir missing]) + usegitver=no + fi +else + AC_MSG_RESULT([no, disabled by configure]) + usegitver=no +fi +AM_CONDITIONAL(USE_GIT_VERSION, test "x$usegitver" = "xyes") + # Enable or disable inclusion of pacman.static AC_MSG_CHECKING(whether to build pacman.static) if test "x$pacmanstatic" = "xyes" ; then @@ -330,7 +363,7 @@ Makefile AC_OUTPUT echo " -pacman_display_version: +${PACKAGE_NAME}: Build information: source code location : ${srcdir} @@ -351,6 +384,7 @@ pacman_display_version: libalpm version : ${LIB_VERSION} libalpm version info : ${LIB_VERSION_INFO} pacman version : ${PACKAGE_VERSION} + using git version : ${usegitver} Directory and file information: root working directory : ${ROOTDIR} @@ -360,6 +394,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..25d5aac2 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -1,9 +1,12 @@ EXTRA_DIST = \ PKGBUILD.vim \ + bacman \ bash_completion \ + gensync \ pacdiff \ + paclist \ 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..5ce7ca40 100644 --- a/contrib/README +++ b/contrib/README @@ -12,11 +12,15 @@ zsh_completion - a zsh completion script, install (with a rename) to pacdiff - a simple pacnew/pacorig/pacsave updater for /etc/. +paclist - list all packages installed from a given repository. Useful for +seeing which packages you may have installed from the testing repository, +for instance. + pacsearch - a colorized search combining both -Ss and -Qs output. Installed packages are easily identified with a *** and local-only packages are also listed. -re-pacman - regenerate a pacman package based on installed files and the pacman +bacman - regenerate a pacman package based on installed files and the pacman database entries. Useful for reuse, or possible config file extension. vimprojects - a project file for the vim project plugin. @@ -24,3 +28,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/bacman b/contrib/bacman new file mode 100755 index 00000000..410482f4 --- /dev/null +++ b/contrib/bacman @@ -0,0 +1,282 @@ +#!/bin/bash +# +# bacman: recreate a package from a running system +# This script rebuilds an already installed package using metadata +# stored into the pacman database and system files +# +# (c) 2008 - locci <carlocci_at_gmail_dot_com> +# +# 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/>. +# + +readonly progname="bacman" +readonly progver="0.2.0" + +# +# User Friendliness +# +function usage(){ + echo "This program recreates a package using pacman's db and system files" + echo "Usage: $progname <installed package name>" + echo "Example: $progname kernel26" +} + +if [ $# -ne 1 ] ; then + usage + exit 1 +fi + +if [ "$1" = "--help" -o "$1" = "-h" ] ; then + usage + exit 0 +fi + +if [ "$1" = "--version" -o "$1" = "-v" ]; then + echo "$progname version $progver" + echo "Copyright (C) 2008 locci" + exit 0 +fi + +# +# Fakeroot support +# +if [ $EUID -gt 0 ]; then + if [ -f /usr/bin/fakeroot ]; then + echo "Entering fakeroot environment" + export INFAKEROOT="1" + /usr/bin/fakeroot -u -- $0 $1 + exit $? + else + echo "WARNING: installing fakeroot or running ${progname} as root is required to" + echo " preserve the ownership permissions of files in some packages" + echo "" + fi +fi + +# +# Setting environmental variables +# +if [ ! -r /etc/pacman.conf ]; then + echo "ERROR: unable to read /etc/pacman.conf" + exit 1 +fi + +eval $(awk '/DBPath/ {print $1$2$3}' /etc/pacman.conf) +pac_db="${DBPath:-/var/lib/pacman/}/local" + +if [ ! -r /etc/makepkg.conf ]; then + echo "ERROR: unable to read /etc/makepkg.conf" + exit 1 +fi + +source "/etc/makepkg.conf" +if [ -r ~/.makepkg.conf ]; then + source ~/.makepkg.conf +fi + +pkg_arch=${CARCH:-'unknown'} +pkg_dest="${PKGDEST:-$PWD}" +pkg_pkger=${PACKAGER:-'Unknown Packager'} + +pkg_name="$1" +pkg_dir="$(echo $pac_db/$pkg_name-[0-9]*)" +pkg_namver="${pkg_dir##*/}" + +# +# Checks everything is in place +# +if [ ! -d "$pac_db" ] ; then + echo "ERROR: pacman database directory ${pac_db} not found" + exit 1 +fi + +if [ ! -d "$pkg_dir" ] ; then + echo "ERROR: package ${pkg_name} not found in pacman database" + exit 1 +fi + +# +# Begin +# +echo Package: ${pkg_namver} +work_dir=$(mktemp -d -p /tmp) +cd $work_dir || exit 1 + +# +# File copying +# +echo "Copying package files..." + +cat "$pkg_dir"/files | +while read i; do + if [ -z "$i" ] ; then + continue + fi + + if [[ "$i" =~ %[A-Z]*% ]] ; then + current=$i + continue + fi + + case $current in + %FILES%) + ret=0 + if [ -e "/$i" ]; then + bsdtar -cnf - "/$i" 2> /dev/null | bsdtar -xpf - + + # Workaround to bsdtar not reporting a missing file as an error + if [ ! -e "$work_dir"/"$i" ]; then + echo "" + echo "ERROR: unable to add /$i to the package" + echo " If your user does not have permssion to read this file then" + echo " you will need to run $progname as root" + rm -rf $work_dir + exit 1 + fi + else + echo "" + echo "WARNING: package file /$i is missing" + echo "" + fi + + + ;; + esac +done + +ret=$? +if [ $ret -ne 0 ]; then + rm -rf $work_dir + exit 1 +fi + +pkg_size=$(du -sk | awk '{print $1 * 1024}') + +if [ -f "$pkg_dir/install" ] ; then + cp "$pkg_dir/install" "$work_dir/.INSTALL" +fi +if [ -f $pkg_dir/changelog ] ; then + cp "$pkg_dir/changelog" "$work_dir/.CHANGELOG" +fi + +# +# .PKGINFO stuff +# +echo Generating .PKGINFO metadata... +echo "# Generated by $progname $progver" > .PKGINFO +if [ "$INFAKEROOT" = "1" ]; then + echo "# Using $(fakeroot -v)" >> .PKGINFO +fi +echo "# $(LC_ALL=C date)" >> .PKGINFO +echo "#" >> .PKGINFO + +cat "$pkg_dir"/{desc,files,depends} | +while read i; do + if [[ -z "$i" ]]; then + continue; + fi + + if [[ "$i" =~ %[A-Z]*% ]] ; then + current=$i + continue + fi + + case "$current" in + # desc + %NAME%) + echo "pkgname = $i" >> .PKGINFO + ;; + %VERSION%) + echo "pkgver = $i" >> .PKGINFO + ;; + %DESC%) + echo "pkgdesc = $i" >> .PKGINFO + ;; + %URL%) + echo "url = $i" >> .PKGINFO + ;; + %LICENSE%) + echo "license = $i" >> .PKGINFO + ;; + %ARCH%) + echo "arch = $i" >> .PKGINFO + ;; + %BUILDDATE%) + echo "builddate = $(date -u "+%s")" >> .PKGINFO + ;; + %PACKAGER%) + echo "packager = $pkg_pkger" >> .PKGINFO + ;; + %SIZE%) + echo "size = $pkg_size" >> .PKGINFO + ;; + %GROUPS%) + echo "group = $i" >> .PKGINFO + ;; + %REPLACES%) + echo "replaces = $i" >> .PKGINFO + ;; + %FORCE%) + echo "force = true" >> .PKGINFO + ;; + + # files + %BACKUP%) + # strip the md5sum after the tab + echo "backup = ${i%%$'\t'*}" >> .PKGINFO + ;; + + # depends + %DEPENDS%) + echo "depend = $i" >> .PKGINFO + ;; + %OPTDEPENDS%) + echo "optdepend = $i" >> .PKGINFO + ;; + %CONFLICTS%) + echo "conflict = $i" >> .PKGINFO + ;; + %PROVIDES%) + echo "provides = $i" >> .PKGINFO + ;; + esac +done + +# +# Fixes owner:group and permissions for .PKGINFO, .CHANGELOG, .INSTALL +# +chown root:root $work_dir/{.PKGINFO,.CHANGELOG,.INSTALL} 2> /dev/null +chmod 644 $work_dir/{.PKGINFO,.CHANGELOG,.INSTALL} 2> /dev/null + +# +# Generate the package +# +echo "Generating the package..." + +ret=0 +bsdtar -czf "$pkg_dest/$pkg_namver-$pkg_arch.tar.gz" $(ls -A) || ret=$? +if [ $ret -ne 0 ]; then + echo "ERROR: unable to write package to $pkg_dest" + echo " Maybe the disk is full or you do not have write access" + rm -rf $work_dir + exit 1 +fi + +rm -rf $work_dir + +echo Done + +exit 0 + +# vim: set ts=2 sw=2 noet:
\ No newline at end of file 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/contrib/paclist b/contrib/paclist new file mode 100755 index 00000000..0379a4c5 --- /dev/null +++ b/contrib/paclist @@ -0,0 +1,88 @@ +#!/usr/bin/perl +# paclist - List all packages installed from a given repo +# +# Copyright (C) 2008 Dan McGee <dpmcgee@gmail.com> +# +# 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/>. + +use strict; +use warnings; + +my $progname = "paclist"; +my $version = "1.0"; + +if ($#ARGV != 0 || $ARGV[0] eq "--help" || $ARGV[0] eq "-h") { + print "$progname - List all packages installed from a given repo\n"; + print "Usage: $progname <repo>\n"; + print "Example: $progname testing\n"; + if ($#ARGV != 0) { + exit 1; + } + exit 0; +} + +if ( $ARGV[0] eq "--version" || $ARGV[0] eq "-v") { + print "$progname version $version\n"; + print "Copyright (C) 2008 Dan McGee\n"; + exit 0; +} + +# This hash table will be used to store pairs of ('name version', count) from +# the return of both pacman -Sl <repo> and pacman -Q output. We then check to +# see if a value was added twice (count = 2)- if so, we will print that package +# as it is both in the repo we queried and installed on our local system. +my %packages = (); +my $output; + +$output = `pacman -Sl $ARGV[0]`; +if ($? != 0) { + exit 1; +} +my @sync = split(/\n/, $output); +# sample output from pacman -Sl: +# testing foobar 1.0-1 +foreach $_ (@sync) { + my @info = split(/ /); + # we only want to store 'foobar 1.0-1' in our hash table + my $pkg = $info[1] . " " . $info[2]; + $packages{$pkg}++; +} + +$output = `pacman -Q`; +if ($? != 0) { + exit 1; +} +# sample output from pacman -Q: +# foobar 1.0-1 +my @local = split(/\n/, $output); +foreach $_ (@local) { + # store 'foobar 1.0-1' in our hash table + $packages{$_}++; +} + +# run comparison check- if value was added twice, it was in the intersection +my @intersection; +foreach $_ (keys %packages) { + if ($packages{$_} == 2) { + push @{ \@intersection }, $_; + } +} + +# print our intersection, and bask in the glory and speed of perl +@intersection = sort @intersection; +foreach $_ (@intersection) { + print $_ . "\n"; +} + +#vim: set noet: diff --git a/contrib/pacsearch b/contrib/pacsearch index c07c28a8..3cf8b925 100755 --- a/contrib/pacsearch +++ b/contrib/pacsearch @@ -1,6 +1,9 @@ -#!/bin/bash +#!/usr/bin/perl # pacsearch - Adds color and install information to a 'pacman -Ss' search # +# Copyright (C) 2008 Dan McGee <dpmcgee@gmail.com> +# +# Based off original shell script version: # Copyright (C) 2006-2007 Dan McGee <dpmcgee@gmail.com> # # This program is free software; you can redistribute it and/or @@ -18,72 +21,112 @@ #TODO: colors flag on commandline -readonly progname="pacsearch" -readonly version="1.0" +use strict; +use warnings; + +my $progname = "pacsearch"; +my $version = "2.0"; + +if ($#ARGV lt 0 || $ARGV[0] eq "--help" || $ARGV[0] eq "-h") { + print "$progname - Add color and install information to a pacman -Ss search\n"; + print "Usage: $progname <pattern>\n"; + print "Example: $progname ^gnome\n"; + if ($#ARGV lt 0) { + exit 1; + } + exit 0; +} -readonly CLR1='\\\e[0;34m' -readonly CLR2='\\\e[0;32m' -readonly CLR3='\\\e[0;35m' -readonly CLR4='\\\e[0;36m' -readonly CLR5='\\\e[0;31m' -readonly CLR6='\\\e[0;33m' -readonly CLR7='\\\e[1;36m' -readonly INST='\\\e[1;31m' -readonly BASE='\\\e[0m' +if ($ARGV[0] eq "--version" || $ARGV[0] eq "-v") { + print "$progname version $version\n"; + print "Copyright (C) 2006-2008 Dan McGee\n"; + exit 0; +} -if [ "$1" = "--help" -o "$1" = "-h" ]; then - echo "Usage: $progname <pattern>" - echo "Ex: $progname ^gnome" - exit 0 -fi +# define our colors to use when printing +my $CLR1 = "\e[0;34m"; +my $CLR2 = "\e[0;32m"; +my $CLR3 = "\e[0;35m"; +my $CLR4 = "\e[0;36m"; +my $CLR5 = "\e[0;31m"; +my $CLR6 = "\e[0;33m"; +my $CLR7 = "\e[1;36m"; +my $INST = "\e[1;31m"; +my $BASE = "\e[0m"; +my $INSTMARK = $INST."***"; -if [ "$1" = "--version" -o "$1" = "-v" ]; then - echo "$progname version $version" - echo "Copyright (C) 2006-2007 Dan McGee" - exit 0 -fi +# color a "repo/pkgname pkgver" line based on the respository name +sub to_color { + my $line = shift; + $line =~ s/(^core\/.*)/$CLR1$1$BASE/; + $line =~ s/(^extra\/.*)/$CLR2$1$BASE/; + $line =~ s/(^community\/.*)/$CLR3$1$BASE/; + $line =~ s/(^testing\/.*)/$CLR4$1$BASE/; + $line =~ s/(^unstable\/.*)/$CLR5$1$BASE/; + $line =~ s/(^custom\/.*)/$CLR6$1$BASE/; + $line =~ s/(^local\/.*)/$CLR7$1$BASE/; + # any other unknown repository + $line =~ s/(^[\w-]*\/.*)/$CLR6$1$BASE/; + return $line; +} -if [ -z "$1" -o "${1:0:1}" = "-" ]; then - echo "Usage: $progname <pattern>" - echo "Ex: $progname ^gnome" - exit 1 -fi +my %allpkgs = (); -# Make two temp files and send output of commands to these files -querydump=$(mktemp) -pacman -Qs $1 > $querydump -syncdump=$(mktemp) -pacman -Ss $1 > $syncdump +my $syncout = `pacman -Ss @ARGV`; +# split each sync search entry into its own array entry +my @syncpkgs = split(/\n^(?=\w)/m, $syncout); +# remove the extra \n from the last desc entry +if ($#syncpkgs >= 0) { + chomp($syncpkgs[$#syncpkgs]); +} -# Strip descriptions and 'local/' from -Qs query -instpkg=$(mktemp) -egrep '^[^ ]' $querydump | sed -e 's@^local/@@' > $instpkg +# counter var for packages, used here and in the query loop too +my $cnt = 0; +foreach $_ (@syncpkgs) { + # we grab 3 fields here: repo, name/ver, and desc + my @pkgfields = /^(.*?)\/(.*?)\n(.*)$/s; + # add a fourth field that will indicate install status + push (@pkgfields, ""); + # add a fifth field that indicates original order + push (@pkgfields, $cnt++); + # add each sync pkg by name/ver to a hash table for quick lookup + $allpkgs{$pkgfields[1]} = [ @pkgfields ]; +} -# Add pkgs not in sync db, mark pkgs that are installed -cat $instpkg | while read -r pkg; do - if [ -z "$(grep "$pkg" $syncdump)" ]; then - # grep package name; pipe to another grep that prints at most one - # line starting with 'local/', allows for comments >1 line - grep -A10 "$pkg" $querydump | grep -A10 -m1 "local/" >> $syncdump - fi - sed -i "s@^\(.\+/$pkg\)@\***\1@" $syncdump -done +my $queryout = `pacman -Qs @ARGV`; +# split each querysearch entry into its own array entry +my @querypkgs = split(/\n^(?=\w)/m, $queryout); +# remove the extra \n from the last desc entry +if ($#querypkgs >= 0) { + chomp ($querypkgs[$#querypkgs]); +} -# Print colorized package list and descriptions to screen -echo -e "$(sed -r \ - -e "s@core/.*@$CLR1&$BASE@" \ - -e "s@extra/.*@$CLR2&$BASE@" \ - -e "s@community/.*@$CLR3&$BASE@" \ - -e "s@testing/.*@$CLR4&$BASE@" \ - -e "s@unstable/.*@$CLR5&$BASE@" \ - -e "s@custom/.*@$CLR6&$BASE@" \ - -e "s@local/.*@$CLR7&$BASE@" \ - -e "s@(^|\*\*\*)([[:alnum:]]*/.* .*)@\1$CLR6\2$BASE@" \ - -e "s@\*\*\*@$INST&@" \ - < $syncdump )" -echo -en "\e[0m" +foreach $_ (@querypkgs) { + # we grab 3 fields here: repo, name/ver, and desc + my @pkgfields = /^(.*?)\/(.*?)\n(.*)$/s; + # check if the package was listed in the sync out + # if it is we want to mark it with a *** marker + if (exists $allpkgs{$pkgfields[1]}) { + # mark it in our fourth field as installed + @{ $allpkgs{$pkgfields[1]} }[3] = $INSTMARK; + } else { + # add a fourth field that will indicate install status + push (@pkgfields, $INSTMARK); + # add a fifth field that indicates original order (after sync) + push (@pkgfields, $cnt++); + # add our local-only package to the hash + $allpkgs{$pkgfields[1]} = [ @pkgfields ]; + } +} -rm $querydump -rm $syncdump -rm $instpkg +# sort by original order (the fifth field) and print +foreach $_ ( sort{ @{$allpkgs{$a}}[4] <=> @{$allpkgs{$b}}[4] } keys %allpkgs) { + my @v = @{$allpkgs{$_}}; + my $line = "$v[0]/$v[1]"; + $line = to_color($line); + # print install marker + colorized "repo/pkgname pkgver" string + print "$v[3]$line\n"; + print "$v[2]\n"; +} +#vim: set noet: diff --git a/contrib/re-pacman b/contrib/re-pacman deleted file mode 100755 index fff1c873..00000000 --- a/contrib/re-pacman +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/sh -# -# re-pacman: regenerate a pacman package based on installed files and the -# pacman database entries. Useful for reuse, or possible config file -# extension -# -# Copyright (c) 2006 Aaron Griffin <aaron@archlinux.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/>. -# - -#TODO -# * Check for md5 changes in backup lines and change pkgrel - -pacinfo () { - [ $# -ne 2 ] && return 1 - #use echo to strip spaces - echo $(pacman -Qi ${1} | grep "${2}" | cut -d: -f2-) -} - -make_pkginfo () { - echo "# Generated by re-pacman 1.0.0" - echo "# On $(date)" - echo "pkgname =$(pacinfo ${1} Name)" - echo "pkgver =$(pacinfo ${1} Version)" - echo "pkgdesc =$(pacinfo ${1} Description)" - echo "url =$(pacinfo ${1} URL)" - echo "builddate =$(pacinfo ${1} 'Build Date')" - echo "packager =$(pacinfo ${1} Packager)" - echo "size =$(pacinfo ${1} Size)" - echo "arch =$(pacinfo ${1} Architecture)" - deps=$(pacinfo ${1} 'Depends On') - for d in ${deps}; do - echo "depend = ${d}" - done -} - -LANG="POSIX" - -if [ $# -ne 1 ]; then - echo "usage: re-pacman <installed package name>" - exit 1 -fi - -ver=$(pacinfo ${1} Version) -if [ "x${ver}" = "x" ]; then - echo "Package '${1}' not found, aborting." - exit 1 -fi - -echo ":: Cleaning up old files" -rm -f .PKGINFO "${1}-${ver}.pkg.tar.gz" - -echo ":: Building PKGINFO" -make_pkginfo ${1} > .PKGINFO - -flist=".PKGINFO" -flist="${flist} $(pacman -Ql ${1} | sed 's|\w* \(.*\)|/\1|g' | grep -v '/$')" - -echo ":: Building final package tarball" -echo ${flist} | tr ' ' '\n' | tar czf "${1}-${ver}.pkg.tar.gz" -T - 2>/dev/null - -rm -f .PKGINFO -echo ":: Package '${1}-${ver}.pkg.tar.gz' is now ready for installation" - -# 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/Makefile.am b/doc/Makefile.am index eba950e3..476a21c3 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -32,6 +32,14 @@ EXTRA_DIST = \ MOSTLYCLEANFILES = *.xml MAINTAINERCLEANFILES = $(ASCIIDOC_MANS) +if USE_GIT_VERSION +GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 | sed s/^v//')-dirty +REAL_PACKAGE_VERSION = $(GIT_VERSION) +else +REAL_PACKAGE_VERSION = $(PACKAGE_VERSION) +endif + + man_MANS = dist_man_MANS = $(ASCIIDOC_MANS) repo-remove.8 @@ -47,7 +55,7 @@ endif if USE_ASCIIDOC ASCIIDOC_OPTS = \ -f asciidoc.conf \ - -a pacman_version="$(PACKAGE_VERSION)" \ + -a pacman_version="$(REAL_PACKAGE_VERSION)" \ -a pacman_date="`date +%Y-%m-%d`" \ -a sysconfdir=$(sysconfdir) A2X_OPTS = \ diff --git a/doc/PKGBUILD-example.txt b/doc/PKGBUILD-example.txt index 2cc53808..0477cb1a 100644 --- a/doc/PKGBUILD-example.txt +++ b/doc/PKGBUILD-example.txt @@ -1,4 +1,4 @@ -# Maintainer: judd <jvinet@zeroflux.org> +# Maintainer: Joe User <joe.user@example.com> pkgname=patch pkgver=2.5.4 @@ -13,8 +13,8 @@ source=(ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.gz) md5sums=('ee5ae84d115f051d87fcaaef3b4ae782') build() { - cd $startdir/src/$pkgname-$pkgver + cd $srcdir/$pkgname-$pkgver ./configure --prefix=/usr make || return 1 - make prefix=$startdir/pkg/usr install + make prefix=$pkgdir/usr install } diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index ac394729..3db51b86 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -89,14 +89,13 @@ Options and Directives source array (in the same order). makepkg will use this to verify source file integrity during subsequent builds. To easily generate md5sums, run ``makepkg -g >> PKGBUILD''. If desired, move the md5sums line to an - appropriate location. *NOTE:* makepkg supports multiple integrity - algorithms and their corresponding arrays (i.e. sha1sums for the SHA1 - algorithm); however, official packages use only md5sums for the time - being. + appropriate location. -*sha1sums, etc.*:: - Alternative integrity checks that makepkg supports, as noted in md5sums - above. +*sha1sums, sha256sums, sha384sums, sha512sums (arrays)*:: + Alternative integrity checks that makepkg supports; these all behave + similar to the md5sums option described above. To enable use and generation + of these checksums, be sure to set up the `INTEGRITY_CHECK` option in + linkman:makepkg.conf[5]. *groups (array)*:: An array of symbolic names that represent groups of packages, allowing @@ -182,6 +181,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/footer.txt b/doc/footer.txt index 15bb479b..8290f3c4 100644 --- a/doc/footer.txt +++ b/doc/footer.txt @@ -15,9 +15,16 @@ mailto:pacman-dev@archlinux.org[]. Authors ------- + +Current maintainers: + +* Dan McGee <dan@archlinux.org> +* Xavier Chantry <shiningxc@gmail.com> +* Aaron Griffin <aaron@archlinux.org> + +Past contributors: + * Judd Vinet <jvinet@zeroflux.org> * Aurelien Foret <aurelien@archlinux.org> -* Aaron Griffin <aaron@archlinux.org> -* Dan McGee <dan@archlinux.org> See the 'AUTHORS' file for additional contributors. diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt index 59108f1b..068cbcb5 100644 --- a/doc/makepkg.8.txt +++ b/doc/makepkg.8.txt @@ -45,13 +45,6 @@ Options for rebuilding packages from source when the PKGBUILD may be slightly outdated and not updated with an `$$arch=('yourarch')$$` field. -*-b, \--builddeps*:: - Build missing dependencies from source. When makepkg finds missing - build-time or run-time dependencies, it will look for the dependencies' - PKGBUILD files under `SRCROOT` (set in linkman:makepkg.conf[5]). If it - finds them it will call makepkg to build and install the missing - dependencies. The child calls will be made with the `-b` and `-i` options. - *-c, \--clean*:: Clean up leftover work files and directories after a successful build. 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..200eba39 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,16 +79,22 @@ 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 doing. *NOTE*: if specified, this is an absolute path and the root path is - not automatically prepended. This behavior changed in pacman 3.1.0. + not automatically prepended. *-d, \--nodeps*:: Skips all dependency checks. Normally, pacman will always check a @@ -113,7 +112,7 @@ Options not be used as a way to install software into ``/usr/local'' instead of ``/usr''. This option is used if you want to install a package on a temporary mounted partition which is "owned" by another system. - *NOTE*: If database path or logfile are not specified on either the + *NOTE*: if database path or logfile are not specified on either the command line or in linkman:pacman.conf[5], their default location will be inside this root path. @@ -124,8 +123,7 @@ Options Specify an alternative package cache location (a typical default is ``/var/cache/pacman/pkg''). Multiple cache directories can be specified, and they are tried in the order they are passed to pacman. *NOTE*: this - is an absolute path, the root path is not automatically prepended. This - behavior changed in pacman 3.1.0. + is an absolute path, the root path is not automatically prepended. *\--config* <'file'>:: Specify an alternate configuration file. @@ -226,7 +224,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 +244,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..20a90671 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 ------- @@ -55,7 +57,7 @@ Options Overrides the default location of the toplevel database directory. A typical default is ``/var/lib/pacman/''. Most users will not need to set this option. *NOTE*: if specified, this is an absolute path and the root - path is not automatically prepended. This behavior changed in pacman 3.1.0. + path is not automatically prepended. *CacheDir =* path/to/cache/dir:: Overrides the default location of the package cache directory. A typical @@ -63,14 +65,13 @@ Options specified, and they are tried in the order they are listed in the config file. If a file is not found in any cache directory, it will be downloaded to the first cache directory with write access. *NOTE*: this is an absolute - path, the root path is not automatically prepended. This behavior changed - in pacman 3.1.0. + path, the root path is not automatically prepended. *LogFile =* '/path/to/file':: - Log actions directly to a file. A typical default is - ``/var/log/pacman.log''. As of pacman 3.1.0, this does not need to be - specified by default. This is an absolute path and root is not prepended. + Overrides the default location of the pacman log file. A typical default + is ``/var/log/pacman.log''. This is an absolute path and the root directory + is not prepended. *HoldPkg =* package ...:: If a user tries to '\--remove' a package that's listed in `HoldPkg`, @@ -80,6 +81,12 @@ Options Instructs pacman to ignore any upgrades for this package when performing a '\--sysupgrade'. +*SyncFirst =* package ...:: + Instructs pacman to check for newer version of these packages before any + sync operation. The user will have the choice to either cancel the current + operation and upgrade these packages first or go on with the current operation. + This option is typically used with the 'pacman' package. + *IgnoreGroup =* group ...:: Instructs pacman to ignore any upgrades for all packages in this group when performing a '\--sysupgrade'. @@ -117,6 +124,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..d3b85762 100644 --- a/doc/repo-add.8.txt +++ b/doc/repo-add.8.txt @@ -16,9 +16,9 @@ repo-add - package database maintenance utility Synopsis -------- -repo-add <path-to-db> [--force] <package> ... +repo-add [-q] <path-to-db> <package> ... -repo-remove <path-to-db> <packagename> ... +repo-remove [-q] <path-to-db> <packagename> ... Description @@ -36,12 +36,9 @@ 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. +*-q, \--quiet*:: + Force this program to keep quiet and run silent except for warning and + error messages. See Also diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index 4da4a63d..47ed0a45 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) @@ -83,8 +84,6 @@ DOC_DIRS=(usr/{,share/}{info,doc,gtk-doc} opt/*/{info,doc,gtk-doc}) #PKGDEST=/home/packages #-- Source cache: specify a fixed directory where source files will be cached #SRCDEST=/home/sources -#-- Source root: specify location where PKGBUILDs are located for '--builddeps' -#SRCROOT=/home/pkgbuilds #-- Packager: name/email of the person or organization building packages #PACKAGER="John Doe <john@doe.com>" diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in index 582fe942..199626db 100644 --- a/etc/pacman.conf.in +++ b/etc/pacman.conf.in @@ -14,6 +14,8 @@ #CacheDir = @localstatedir@/cache/pacman/pkg/ #LogFile = @localstatedir@/log/pacman.log HoldPkg = pacman glibc +# If upgrades are available for these packages they will be asked for first +SyncFirst = pacman #XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index 14d42a0c..871855ef 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -26,19 +26,21 @@ libalpm_la_SOURCES = \ alpm_list.h alpm_list.c \ backup.h backup.c \ be_files.c \ + be_package.c \ cache.h cache.c \ conflict.h conflict.c \ 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..6cf865ab 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -27,6 +27,8 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <inttypes.h> /* int64_t */ +#include <stdint.h> /* intmax_t */ /* libarchive */ #include <archive.h> @@ -37,7 +39,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 +69,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_pkg_vercmp(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); @@ -113,15 +98,6 @@ error: return(-1); } - -/* This is still messy. We have a lot of compare functions, and we should - * try to consolidate them as much as we can (between add and sync) */ -/*static int deppkg_cmp(const void *p1, const void *p2) -{ - return(strcmp(((pmdepmissing_t *)p1)->target, - ((pmdepmissing_t *)p2)->target)); -}*/ - int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) { alpm_list_t *lp = NULL; @@ -138,12 +114,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 +144,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 +152,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 +170,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 +188,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); @@ -290,29 +271,30 @@ static int extract_single_file(struct archive *archive, struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg, pmtrans_t *trans, pmdb_t *db) { - char entryname[PATH_MAX]; /* the name of the file in the archive */ + const char *entryname; mode_t entrymode; char filename[PATH_MAX]; /* the actual file we're extracting */ int needbackup = 0, notouch = 0; char *hash_orig = NULL; + char *entryname_orig = NULL; const int archive_flags = ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME; int errors = 0; - strncpy(entryname, archive_entry_pathname(entry), PATH_MAX); + entryname = archive_entry_pathname(entry); entrymode = archive_entry_mode(entry); memset(filename, 0, PATH_MAX); /* just to be sure */ if(strcmp(entryname, ".INSTALL") == 0) { /* the install script goes inside the db */ - snprintf(filename, PATH_MAX, "%s/%s-%s/install", db->path, + snprintf(filename, PATH_MAX, "%s%s-%s/install", db->path, newpkg->name, newpkg->version); archive_entry_set_mode(entry, 0644); } else if(strcmp(entryname, ".CHANGELOG") == 0) { /* the changelog goes inside the db */ - snprintf(filename, PATH_MAX, "%s/%s-%s/changelog", db->path, + snprintf(filename, PATH_MAX, "%s%s-%s/changelog", db->path, newpkg->name, newpkg->version); archive_entry_set_mode(entry, 0644); } else if(*entryname == '.') { @@ -338,7 +320,8 @@ static int extract_single_file(struct archive *archive, /* if a file is in the add skiplist we never extract it */ if(alpm_list_find_str(trans->skip_add, filename)) { - _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_add, skipping extraction\n", entryname); + _alpm_log(PM_LOG_DEBUG, "%s is in trans->skip_add, skipping extraction\n", + entryname); archive_read_data_skip(archive); return(0); } @@ -437,7 +420,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)); } } } @@ -445,34 +428,35 @@ static int extract_single_file(struct archive *archive, /* case 5,8: don't need to do anything special */ } + /* we need access to the original entryname later after calls to + * archive_entry_set_pathname(), so we need to dupe it and free() later */ + STRDUP(entryname_orig, entryname, RET_ERR(PM_ERR_MEMORY, -1)); + 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", - entryname, archive_error_string(archive)); + entryname_orig, archive_error_string(archive)); } else if(ret != ARCHIVE_OK) { _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), - entryname, archive_error_string(archive)); + entryname_orig, archive_error_string(archive)); alpm_logaction("error: could not extract %s (%s)\n", - entryname, archive_error_string(archive)); - unlink(tempfile); - FREE(tempfile); + entryname_orig, archive_error_string(archive)); FREE(hash_orig); + FREE(entryname_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) */ @@ -480,16 +464,13 @@ static int extract_single_file(struct archive *archive, for(backups = alpm_pkg_get_backup(newpkg); backups; backups = alpm_list_next(backups)) { char *oldbackup = alpm_list_getdata(backups); - if(!oldbackup || strcmp(oldbackup, entryname) != 0) { + if(!oldbackup || strcmp(oldbackup, entryname_orig) != 0) { continue; } 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'; @@ -497,7 +478,7 @@ static int extract_single_file(struct archive *archive, backups->data = backup; } - _alpm_log(PM_LOG_DEBUG, "checking hashes for %s\n", entryname); + _alpm_log(PM_LOG_DEBUG, "checking hashes for %s\n", entryname_orig); _alpm_log(PM_LOG_DEBUG, "current: %s\n", hash_local); _alpm_log(PM_LOG_DEBUG, "new: %s\n", hash_pkg); _alpm_log(PM_LOG_DEBUG, "original: %s\n", hash_orig); @@ -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); } @@ -536,38 +518,48 @@ static int extract_single_file(struct archive *archive, /* installed file has NOT been changed by user */ if(strcmp(hash_orig, hash_pkg) != 0) { _alpm_log(PM_LOG_DEBUG, "action: installing new file: %s\n", - entryname); + entryname_orig); - 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"); + _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 +567,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,16 +590,17 @@ 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", - entryname, archive_error_string(archive)); + entryname_orig, archive_error_string(archive)); } else if(ret != ARCHIVE_OK) { _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), - entryname, archive_error_string(archive)); + entryname_orig, archive_error_string(archive)); alpm_logaction("error: could not extract %s (%s)\n", - entryname, archive_error_string(archive)); + entryname_orig, archive_error_string(archive)); + FREE(entryname_orig); return(1); } @@ -617,18 +610,15 @@ 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) { + if(!oldbackup || strcmp(oldbackup, entryname_orig) != 0) { continue; } _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'; @@ -637,6 +627,7 @@ static int extract_single_file(struct archive *archive, b->data = backup; } } + FREE(entryname_orig); return(errors); } @@ -644,14 +635,12 @@ 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 +655,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 +677,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 +693,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); @@ -734,17 +731,22 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, } for(i = 0; archive_read_next_header(archive, &entry) == ARCHIVE_OK; i++) { + double percent; + if(newpkg->size != 0) { /* Using compressed size for calculations here, as newpkg->isize is not * exact when it comes to comparing to the ACTUAL uncompressed size * (missing metadata sizes) */ - unsigned long pos = archive_position_compressed(archive); + int64_t pos = archive_position_compressed(archive); percent = (double)pos / (double)newpkg->size; - _alpm_log(PM_LOG_DEBUG, "decompression progress: %f%% (%ld / %ld)\n", - percent*100.0, pos, newpkg->size); + _alpm_log(PM_LOG_DEBUG, "decompression progress: " + "%f%% (%"PRId64" / %jd)\n", + percent*100.0, pos, (intmax_t)newpkg->size); if(percent >= 1.0) { percent = 1.0; } + } else { + percent = 0.0; } if(is_upgrade) { @@ -810,7 +812,6 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count, PROGRESS(trans, PM_TRANS_PROGRESS_ADD_START, alpm_pkg_get_name(newpkg), 100, pkg_count, pkg_current); } - EVENT(trans, PM_TRANS_EVT_EXTRACT_DONE, NULL, NULL); /* run the post-install script if it exists */ if(alpm_pkg_has_scriptlet(newpkg) @@ -850,7 +851,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..9ed2c676 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -1,7 +1,7 @@ /* * alpm.h * - * Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> + * Copyright (c) 2002-2008 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) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -26,6 +26,7 @@ extern "C" { #endif +#include <sys/types.h> /* for off_t */ #include <time.h> /* for time_t */ #include <stdarg.h> /* for va_list */ @@ -45,14 +46,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,21 +80,23 @@ 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, + off_t xfered, off_t total); +typedef void (*alpm_cb_totaldl)(off_t total); /* * Options */ -#define PM_DLFNM_LEN 22 - alpm_cb_log alpm_option_get_logcb(); void alpm_option_set_logcb(alpm_cb_log cb); alpm_cb_download alpm_option_get_dlcb(); void alpm_option_set_dlcb(alpm_cb_download cb); +alpm_cb_totaldl alpm_option_get_totaldlcb(); +void alpm_option_set_totaldlcb(alpm_cb_totaldl cb); + const char *alpm_option_get_root(); int alpm_option_set_root(const char *root); @@ -170,7 +171,6 @@ int alpm_db_update(int level, pmdb_t *db); pmpkg_t *alpm_db_get_pkg(pmdb_t *db, const char *name); alpm_list_t *alpm_db_getpkgcache(pmdb_t *db); -alpm_list_t *alpm_db_whatprovides(pmdb_t *db, const char *name); pmgrp_t *alpm_db_readgrp(pmdb_t *db, const char *name); alpm_list_t *alpm_db_getgrpcache(pmdb_t *db); @@ -192,7 +192,7 @@ int alpm_pkg_load(const char *filename, unsigned short full, pmpkg_t **pkg); int alpm_pkg_free(pmpkg_t *pkg); int alpm_pkg_checkmd5sum(pmpkg_t *pkg); char *alpm_fetch_pkgurl(const char *url); -int alpm_pkg_vercmp(const char *ver1, const char *ver2); +int alpm_pkg_vercmp(const char *a, const char *b); alpm_list_t *alpm_pkg_compute_requiredby(pmpkg_t *pkg); const char *alpm_pkg_get_filename(pmpkg_t *pkg); @@ -205,8 +205,8 @@ time_t alpm_pkg_get_installdate(pmpkg_t *pkg); const char *alpm_pkg_get_packager(pmpkg_t *pkg); const char *alpm_pkg_get_md5sum(pmpkg_t *pkg); const char *alpm_pkg_get_arch(pmpkg_t *pkg); -unsigned long alpm_pkg_get_size(pmpkg_t *pkg); -unsigned long alpm_pkg_get_isize(pmpkg_t *pkg); +off_t alpm_pkg_get_size(pmpkg_t *pkg); +off_t alpm_pkg_get_isize(pmpkg_t *pkg); pmpkgreason_t alpm_pkg_get_reason(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_licenses(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_groups(pmpkg_t *pkg); @@ -225,38 +225,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); +off_t 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); +off_t 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 +261,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 +276,103 @@ 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, - 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 +405,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 +429,17 @@ 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); +alpm_list_t *alpm_find_pkg_satisfiers(alpm_list_t *pkgs, const char *pkgname); 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 +494,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 +509,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 +525,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..87567402 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; @@ -327,7 +307,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, const void *needl continue; } tmp = i->next; - if(fn(needle, i->data) == 0) { + if(fn(i->data, needle) == 0) { /* we found a matching item */ if(i == haystack) { /* Special case: removing the head node which has a back reference to @@ -371,6 +351,22 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, const void *needl } /** + * @brief Remove a string from a list. + * + * @param haystack the list to remove the item from + * @param needle the data member of the item we're removing + * @param data output parameter containing data of the removed item + * + * @return the resultant list + */ +alpm_list_t SYMEXPORT *alpm_list_remove_str(alpm_list_t *haystack, + const char *needle, char **data) +{ + return(alpm_list_remove(haystack, (const void *)needle, + (alpm_list_fn_cmp)strcmp, (void **)data)); +} + +/** * @brief Create a new list without any duplicates. * * This does NOT copy data members. @@ -464,18 +460,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 +490,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 +523,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); + } } /** @@ -594,7 +602,7 @@ void SYMEXPORT *alpm_list_find(const alpm_list_t *haystack, const void *needle, } /* trivial helper function for alpm_list_find_ptr */ -static int ptrcmp(const void *p, const void *q) +static int ptr_cmp(const void *p, const void *q) { return(p != q); } @@ -611,7 +619,7 @@ static int ptrcmp(const void *p, const void *q) */ void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, const void *needle) { - return(alpm_list_find(haystack, needle, ptrcmp)); + return(alpm_list_find(haystack, needle, ptr_cmp)); } /** @@ -622,9 +630,11 @@ void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, const void *need * * @return `needle` if found, NULL otherwise */ -char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, const char *needle) +char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, + const char *needle) { - return((char *)alpm_list_find(haystack, (const void*)needle, (alpm_list_fn_cmp)strcmp)); + return((char *)alpm_list_find(haystack, (const void*)needle, + (alpm_list_fn_cmp)strcmp)); } /** diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index ae373910..8dc8c5ff 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); @@ -56,6 +57,7 @@ alpm_list_t *alpm_list_join(alpm_list_t *first, alpm_list_t *second); alpm_list_t *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, alpm_list_fn_cmp fn); alpm_list_t *alpm_list_msort(alpm_list_t *list, int n, alpm_list_fn_cmp fn); alpm_list_t *alpm_list_remove(alpm_list_t *haystack, const void *needle, alpm_list_fn_cmp fn, void **data); +alpm_list_t *alpm_list_remove_str(alpm_list_t *haystack, const char *needle, char **data); alpm_list_t *alpm_list_remove_dupes(const alpm_list_t *list); alpm_list_t *alpm_list_strdup(const alpm_list_t *list); alpm_list_t *alpm_list_copy(const alpm_list_t *list); diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c index 4cd0985e..12c60b24 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -25,7 +25,7 @@ #include <stdlib.h> #include <errno.h> #include <string.h> -#include <stdint.h> /* uintmax_t */ +#include <stdint.h> /* uintmax_t, intmax_t */ #include <sys/stat.h> #include <dirent.h> #include <ctype.h> @@ -36,32 +36,182 @@ /* libalpm */ #include "db.h" #include "alpm_list.h" +#include "cache.h" #include "log.h" #include "util.h" #include "alpm.h" -#include "error.h" #include "handle.h" #include "package.h" #include "delta.h" #include "deps.h" +#include "dload.h" -/* This function is used to convert the downloaded db file to the proper backend - * format +/* + * Return the last update time as number of seconds from the epoch. + * Returns 0 if the value is unknown or can't be read. */ -int _alpm_db_install(pmdb_t *db, const char *dbfile) +time_t getlastupdate(const pmdb_t *db) { + FILE *fp; + char *file; + time_t ret = 0; + ALPM_LOG_FUNC; - /* TODO we should not simply unpack the archive, but better parse it and - * db_write each entry (see sync_load_dbarchive to get archive content) */ - _alpm_log(PM_LOG_DEBUG, "unpacking database '%s'\n", dbfile); + if(db == NULL) { + return(ret); + } + + /* db->path + '.lastupdate' + NULL */ + MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); + sprintf(file, "%s.lastupdate", db->path); - if(_alpm_unpack(dbfile, db->path, NULL)) { - RET_ERR(PM_ERR_SYSTEM, -1); + /* get the last update time, if it's there */ + if((fp = fopen(file, "r")) == NULL) { + free(file); + return(ret); + } else { + char line[64]; + if(fgets(line, sizeof(line), fp)) { + ret = atol(line); + } } + fclose(fp); + free(file); + return(ret); +} - return unlink(dbfile); +/* + * writes the dbpath/.lastupdate file with the value in time + */ +int setlastupdate(const pmdb_t *db, time_t time) +{ + FILE *fp; + char *file; + int ret = 0; + + ALPM_LOG_FUNC; + + if(db == NULL || time == 0) { + return(-1); + } + + /* db->path + '.lastupdate' + NULL */ + MALLOC(file, strlen(db->path) + 12, RET_ERR(PM_ERR_MEMORY, ret)); + sprintf(file, "%s.lastupdate", db->path); + + if((fp = fopen(file, "w")) == NULL) { + free(file); + return(-1); + } + if(fprintf(fp, "%ju", (uintmax_t)time) <= 0) { + ret = -1; + } + fclose(fp); + free(file); + return(ret); +} + +/** Update a package database + * @param force if true, then forces the update, otherwise update only in case + * the database isn't up to date + * @param db pointer to the package database to update + * @return 0 on success, > 0 on error (pm_errno is set accordingly), < 0 if up + * to date + */ +int SYMEXPORT alpm_db_update(int force, pmdb_t *db) +{ + alpm_list_t *lp; + char *dbfile, *dbfilepath; + time_t newmtime = 0, lastupdate = 0; + const char *dbpath; + size_t len; + + int ret; + + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + ASSERT(db != NULL && db != handle->db_local, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + /* Verify we are in a transaction. This is done _mainly_ because we need a DB + * lock - if we update without a db lock, we may kludge some other pacman + * process that _has_ a lock. + */ + ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(handle->trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1)); + + if(!alpm_list_find_ptr(handle->dbs_sync, db)) { + RET_ERR(PM_ERR_DB_NOT_FOUND, -1); + } + + if(!force) { + /* get the lastupdate time */ + lastupdate = getlastupdate(db); + if(lastupdate == 0) { + _alpm_log(PM_LOG_DEBUG, "failed to get lastupdate time for %s\n", + db->treename); + } + } + + len = strlen(db->treename) + strlen(DBEXT) + 1; + MALLOC(dbfile, len, RET_ERR(PM_ERR_MEMORY, -1)); + sprintf(dbfile, "%s" DBEXT, db->treename); + + dbpath = alpm_option_get_dbpath(); + + ret = _alpm_download_single_file(dbfile, db->servers, dbpath, + lastupdate, &newmtime); + free(dbfile); + + if(ret == 1) { + /* mtimes match, do nothing */ + pm_errno = 0; + return(1); + } else if(ret == -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 { + /* remove the old dir */ + _alpm_log(PM_LOG_DEBUG, "flushing database %s\n", db->path); + for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { + pmpkg_t *pkg = lp->data; + if(pkg && _alpm_db_remove(db, pkg) == -1) { + _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s%s\n"), + db->treename, pkg->name); + RET_ERR(PM_ERR_DB_REMOVE, -1); + } + } + + /* Cache needs to be rebuilt */ + _alpm_db_free_pkgcache(db); + + /* form the path to the db location */ + len = strlen(dbpath) + strlen(db->treename) + strlen(DBEXT) + 1; + MALLOC(dbfilepath, len, RET_ERR(PM_ERR_MEMORY, -1)); + sprintf(dbfilepath, "%s%s" DBEXT, dbpath, db->treename); + + /* uncompress the sync database */ + ret = _alpm_unpack(dbfilepath, db->path, NULL); + if(ret) { + free(dbfilepath); + RET_ERR(PM_ERR_SYSTEM, -1); + } + unlink(dbfilepath); + free(dbfilepath); + + /* 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); + setlastupdate(db, newmtime); + } + } + + return(0); } int _alpm_db_open(pmdb_t *db) @@ -95,18 +245,7 @@ void _alpm_db_close(pmdb_t *db) } } -void _alpm_db_rewind(pmdb_t *db) -{ - ALPM_LOG_FUNC; - - if(db == NULL || db->handle == NULL) { - return; - } - - 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 +254,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,120 +269,96 @@ 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); } -pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target) +int _alpm_db_populate(pmdb_t *db) { + int count = 0; 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; ALPM_LOG_FUNC; - if(db == NULL) { - RET_ERR(PM_ERR_DB_NULL, NULL); - } + ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - /* We loop here until we read a valid package. When an iteration of this loop - * fails, it means alpm_db_read failed to read a valid package, so we'll read - * the next so as not to abort whole-db operations early - */ - while(!pkg) { - if(target != NULL) { - /* 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, "..")) { - continue; - } - /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); - if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { - continue; - } - strncpy(name, ent->d_name, PKG_FULLNAME_LEN); - /* truncate the string at the second-to-last hyphen, */ - /* which will give us the package name */ - if((ptr = rindex(name, '-'))) { - *ptr = '\0'; - } - if((ptr = rindex(name, '-'))) { - *ptr = '\0'; - } - if(!strcmp(name, target)) { - found = 1; - } - } - if(!found) { - return(NULL); - } - } else { /* target == NULL, full scan */ - int isdir = 0; - while(!isdir) { - ent = readdir(db->handle); - if(ent == NULL) { - return(NULL); - } - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { - isdir = 0; - continue; - } - /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); - if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { - isdir = 1; - } - } + rewinddir(db->handle); + while((ent = readdir(db->handle)) != NULL) { + const char *name = ent->d_name; + pmpkg_t *pkg; + + if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + continue; + } + /* stat the entry, make sure it's a directory */ + snprintf(path, PATH_MAX, "%s%s", db->path, name); + if(stat(path, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) { + continue; } - pkg = _alpm_pkg_new(NULL, NULL); + pkg = _alpm_pkg_new(); if(pkg == NULL) { - _alpm_log(PM_LOG_DEBUG, "db scan could not find package: %s\n", target); - return(NULL); + return(-1); } /* split the db entry name */ - if(_alpm_db_splitname(ent->d_name, pkg->name, pkg->version) != 0) { + if(splitname(name, pkg) != 0) { _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), - ent->d_name); - alpm_pkg_free(pkg); - pkg = NULL; + name); + _alpm_pkg_free(pkg); continue; } /* explicitly read with only 'BASE' data, accessors will handle the rest */ if(_alpm_db_read(db, pkg, INFRQ_BASE) == -1) { - /* TODO removed corrupt entry from the FS here */ + _alpm_log(PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name); _alpm_pkg_free(pkg); - } else { - pkg->origin = PKG_FROM_CACHE; - pkg->origin_data.db = db; + continue; } + pkg->origin = PKG_FROM_CACHE; + pkg->origin_data.db = db; + /* add to the collection */ + _alpm_log(PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", + pkg->name, db->treename); + db->pkgcache = alpm_list_add(db->pkgcache, pkg); + count++; } - return(pkg); + db->pkgcache = alpm_list_msort(db->pkgcache, count, _alpm_pkg_cmp); + return(count); +} + +/* Note: the return value must be freed by the caller */ +static char *get_pkgpath(pmdb_t *db, pmpkg_t *info) +{ + size_t len; + char *pkgpath; + + len = strlen(db->path) + strlen(info->name) + strlen(info->version) + 3; + MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL)); + sprintf(pkgpath, "%s%s-%s/", db->path, info->name, info->version); + return(pkgpath); } int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) { FILE *fp = NULL; struct stat buf; - char path[PATH_MAX+1]; + char path[PATH_MAX]; char line[513]; + char *pkgpath = NULL; ALPM_LOG_FUNC; @@ -251,7 +366,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); } @@ -276,17 +391,18 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) /* clear out 'line', to be certain - and to make valgrind happy */ memset(line, 0, 513); - snprintf(path, PATH_MAX, "%s/%s-%s", db->path, info->name, info->version); - if(stat(path, &buf)) { + pkgpath = get_pkgpath(db, info); + + if(stat(pkgpath, &buf)) { /* directory doesn't exist or can't be opened */ _alpm_log(PM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", info->name, info->version, db->treename); - return(-1); + goto error; } /* DESC */ if(inforeq & INFRQ_DESC) { - snprintf(path, PATH_MAX, "%s/%s-%s/desc", db->path, info->name, info->version); + snprintf(path, PATH_MAX, "%sdesc", pkgpath); if((fp = fopen(path, "r")) == NULL) { _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; @@ -296,120 +412,131 @@ 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, "%NAME%") == 0) { + if(fgets(line, 512, fp) == NULL) { + goto error; + } + if(strcmp(_alpm_strtrim(line), info->name) != 0) { + _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: name " + "mismatch on package %s\n"), db->treename, info->name); + } + } else if(strcmp(line, "%VERSION%") == 0) { + if(fgets(line, 512, fp) == NULL) { + goto error; + } + if(strcmp(_alpm_strtrim(line), info->version) != 0) { + _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: version " + "mismatch on package %s\n"), db->treename, info->name); + } + } else 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; } } @@ -419,20 +546,24 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) /* FILES */ if(inforeq & INFRQ_FILES) { - snprintf(path, PATH_MAX, "%s/%s-%s/files", db->path, info->name, info->version); + snprintf(path, PATH_MAX, "%sfiles", pkgpath); if((fp = fopen(path, "r")) == NULL) { _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; } 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); } } } @@ -442,7 +573,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) /* DEPENDS */ if(inforeq & INFRQ_DEPENDS) { - snprintf(path, PATH_MAX, "%s/%s-%s/depends", db->path, info->name, info->version); + snprintf(path, PATH_MAX, "%sdepends", pkgpath); if((fp = fopen(path, "r")) == NULL) { _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; @@ -450,37 +581,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 +612,12 @@ 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, "%sdeltas", pkgpath); 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)); } @@ -506,7 +630,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) /* INSTALL */ if(inforeq & INFRQ_SCRIPTLET) { - snprintf(path, PATH_MAX, "%s/%s-%s/install", db->path, info->name, info->version); + snprintf(path, PATH_MAX, "%sinstall", pkgpath); if(!stat(path, &buf)) { info->scriptlet = 1; } @@ -515,9 +639,11 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) /* internal */ info->infolevel |= inforeq; + free(pkgpath); return(0); error: + free(pkgpath); if(fp) { fclose(fp); } @@ -532,6 +658,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) alpm_list_t *lp = NULL; int retval = 0; int local = 0; + char *pkgpath = NULL; ALPM_LOG_FUNC; @@ -539,9 +666,10 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) return(-1); } - snprintf(path, PATH_MAX, "%s/%s-%s", db->path, info->name, info->version); + pkgpath = get_pkgpath(db, info); + oldmask = umask(0000); - mkdir(path, 0755); + mkdir(pkgpath, 0755); /* make sure we have a sane umask */ umask(0022); @@ -553,7 +681,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(inforeq & INFRQ_DESC) { _alpm_log(PM_LOG_DEBUG, "writing %s-%s DESC information back to db\n", info->name, info->version); - snprintf(path, PATH_MAX, "%s/%s-%s/desc", db->path, info->name, info->version); + snprintf(path, PATH_MAX, "%sdesc", pkgpath); if((fp = fopen(path, "w")) == NULL) { _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); retval = -1; @@ -561,7 +689,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); } @@ -572,8 +700,18 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) } fprintf(fp, "\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) { + fprintf(fp, "%%FORCE%%\n\n"); + } if(local) { - if(info->url[0]) { + if(info->url) { fprintf(fp, "%%URL%%\n" "%s\n\n", info->url); } @@ -584,7 +722,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,14 +734,14 @@ 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); } - if(info->size) { + if(info->isize) { /* only write installed size, csize is irrelevant once installed */ fprintf(fp, "%%SIZE%%\n" - "%lu\n\n", info->isize); + "%ju\n\n", (intmax_t)info->isize); } if(info->reason) { fprintf(fp, "%%REASON%%\n" @@ -612,11 +750,11 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) } else { if(info->size) { fprintf(fp, "%%CSIZE%%\n" - "%lu\n\n", info->size); + "%ju\n\n", (intmax_t)info->size); } if(info->isize) { fprintf(fp, "%%ISIZE%%\n" - "%lu\n\n", info->isize); + "%ju\n\n", (intmax_t)info->isize); } if(info->md5sum) { fprintf(fp, "%%MD5SUM%%\n" @@ -631,7 +769,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(local && (inforeq & INFRQ_FILES)) { _alpm_log(PM_LOG_DEBUG, "writing %s-%s FILES information back to db\n", info->name, info->version); - snprintf(path, PATH_MAX, "%s/%s-%s/files", db->path, info->name, info->version); + snprintf(path, PATH_MAX, "%sfiles", pkgpath); if((fp = fopen(path, "w")) == NULL) { _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); retval = -1; @@ -659,7 +797,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(inforeq & INFRQ_DEPENDS) { _alpm_log(PM_LOG_DEBUG, "writing %s-%s DEPENDS information back to db\n", info->name, info->version); - snprintf(path, PATH_MAX, "%s/%s-%s/depends", db->path, info->name, info->version); + snprintf(path, PATH_MAX, "%sdepends", pkgpath); if((fp = fopen(path, "w")) == NULL) { _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); retval = -1; @@ -695,19 +833,6 @@ 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"); - } - } fclose(fp); fp = NULL; } @@ -717,6 +842,7 @@ int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) cleanup: umask(oldmask); + free(pkgpath); if(fp) { fclose(fp); @@ -727,7 +853,8 @@ cleanup: int _alpm_db_remove(pmdb_t *db, pmpkg_t *info) { - char path[PATH_MAX]; + int ret = 0; + char *pkgpath = NULL; ALPM_LOG_FUNC; @@ -735,70 +862,13 @@ int _alpm_db_remove(pmdb_t *db, pmpkg_t *info) RET_ERR(PM_ERR_DB_NULL, -1); } - snprintf(path, PATH_MAX, "%s%s-%s", db->path, info->name, info->version); - if(_alpm_rmrf(path) == -1) { - return(-1); - } - - return(0); -} - -/* - * Return the last update time as number of seconds from the epoch. - * Returns 0 if the value is unknown or can't be read. - */ -time_t _alpm_db_getlastupdate(const pmdb_t *db) -{ - FILE *fp; - char file[PATH_MAX]; - time_t ret = 0; - - ALPM_LOG_FUNC; - - if(db == NULL) { - return(ret); - } - - snprintf(file, PATH_MAX, "%s.lastupdate", db->path); - - /* get the last update time, if it's there */ - if((fp = fopen(file, "r")) == NULL) { - return(ret); - } else { - char line[64]; - if(fgets(line, sizeof(line), fp)) { - ret = atol(line); - } - } - fclose(fp); - return(ret); -} - -/* - * writes the dbpath/.lastupdate file with the value in time - */ -int _alpm_db_setlastupdate(const pmdb_t *db, time_t time) -{ - FILE *fp; - char file[PATH_MAX]; - int ret = 0; - - ALPM_LOG_FUNC; - - if(db == NULL || time == 0) { - return(-1); - } - - snprintf(file, PATH_MAX, "%s.lastupdate", db->path); + pkgpath = get_pkgpath(db, info); - if((fp = fopen(file, "w")) == NULL) { - return(-1); - } - if(fprintf(fp, "%ju", (uintmax_t)time) <= 0) { + ret = _alpm_rmrf(pkgpath); + free(pkgpath); + if(ret != 0) { ret = -1; } - fclose(fp); - return(ret); } diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c new file mode 100644 index 00000000..c0ec3bcf --- /dev/null +++ b/lib/libalpm/be_package.c @@ -0,0 +1,288 @@ +/* + * be_package.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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> +#include <locale.h> /* setlocale */ + +/* libarchive */ +#include <archive.h> +#include <archive_entry.h> + +/* libalpm */ +#include "alpm_list.h" +#include "util.h" +#include "log.h" +#include "package.h" +#include "deps.h" /* _alpm_splitdep */ + +/** + * Parses the package description file for a package into a pmpkg_t struct. + * @param archive the archive to read from, pointed at the .PKGINFO entry + * @param newpkg an empty pmpkg_t struct to fill with package info + * + * @return 0 on success, 1 on error + */ +static int parse_descfile(struct archive *a, pmpkg_t *newpkg) +{ + char line[PATH_MAX]; + char *ptr = NULL; + char *key = NULL; + int linenum = 0; + + ALPM_LOG_FUNC; + + /* 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] == '#') { + continue; + } + ptr = line; + key = strsep(&ptr, "="); + if(key == NULL || ptr == NULL) { + _alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", + newpkg->name ? newpkg->name : "error", linenum); + } else { + key = _alpm_strtrim(key); + ptr = _alpm_strtrim(ptr); + if(!strcmp(key, "pkgname")) { + STRDUP(newpkg->name, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + } else if(!strcmp(key, "pkgver")) { + STRDUP(newpkg->version, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + } else if(!strcmp(key, "pkgdesc")) { + STRDUP(newpkg->desc, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + } else if(!strcmp(key, "group")) { + newpkg->groups = alpm_list_add(newpkg->groups, strdup(ptr)); + } else if(!strcmp(key, "url")) { + STRDUP(newpkg->url, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + } else if(!strcmp(key, "license")) { + newpkg->licenses = alpm_list_add(newpkg->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 in case of failure + setlocale(LC_TIME, "C"); + strptime(ptr, "%a %b %e %H:%M:%S %Y", &tmp_tm); + newpkg->builddate = mktime(&tmp_tm); + setlocale(LC_TIME, ""); + } else { + newpkg->builddate = atol(ptr); + } + } else if(!strcmp(key, "packager")) { + STRDUP(newpkg->packager, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + } else if(!strcmp(key, "arch")) { + STRDUP(newpkg->arch, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + } else if(!strcmp(key, "size")) { + /* size in the raw package is uncompressed (installed) size */ + newpkg->isize = atol(ptr); + } else if(!strcmp(key, "depend")) { + pmdepend_t *dep = _alpm_splitdep(ptr); + newpkg->depends = alpm_list_add(newpkg->depends, dep); + } else if(!strcmp(key, "optdepend")) { + newpkg->optdepends = alpm_list_add(newpkg->optdepends, strdup(ptr)); + } else if(!strcmp(key, "conflict")) { + newpkg->conflicts = alpm_list_add(newpkg->conflicts, strdup(ptr)); + } else if(!strcmp(key, "replaces")) { + newpkg->replaces = alpm_list_add(newpkg->replaces, strdup(ptr)); + } else if(!strcmp(key, "provides")) { + newpkg->provides = alpm_list_add(newpkg->provides, strdup(ptr)); + } else if(!strcmp(key, "backup")) { + newpkg->backup = alpm_list_add(newpkg->backup, strdup(ptr)); + } else { + _alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", + newpkg->name ? newpkg->name : "error", linenum); + } + } + line[0] = '\0'; + } + + return(0); +} + +/** + * Load a package and create the corresponding pmpkg_t struct. + * @param pkgfile path to the package file + * @param full whether to stop the load after metadata is read or continue + * through the full archive + * @return An information filled pmpkg_t struct + */ +static pmpkg_t *pkg_load(const char *pkgfile, unsigned short full) +{ + int ret = ARCHIVE_OK; + int config = 0; + struct archive *archive; + struct archive_entry *entry; + pmpkg_t *newpkg = NULL; + struct stat st; + + ALPM_LOG_FUNC; + + if(pkgfile == NULL || strlen(pkgfile) == 0) { + RET_ERR(PM_ERR_WRONG_ARGS, NULL); + } + + if(stat(pkgfile, &st) != 0) { + RET_ERR(PM_ERR_PKG_OPEN, NULL); + } + + if((archive = archive_read_new()) == NULL) { + RET_ERR(PM_ERR_LIBARCHIVE, NULL); + } + + archive_read_support_compression_all(archive); + archive_read_support_format_all(archive); + + if (archive_read_open_filename(archive, pkgfile, + ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { + RET_ERR(PM_ERR_PKG_OPEN, NULL); + } + + newpkg = _alpm_pkg_new(); + if(newpkg == NULL) { + archive_read_finish(archive); + RET_ERR(PM_ERR_MEMORY, NULL); + } + + newpkg->filename = strdup(pkgfile); + newpkg->size = st.st_size; + + /* 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); + + if(strcmp(entry_name, ".PKGINFO") == 0) { + /* parse the info file */ + if(parse_descfile(archive, newpkg) != 0) { + _alpm_log(PM_LOG_ERROR, _("could not parse package description file in %s\n"), + pkgfile); + goto pkg_invalid; + } + if(newpkg->name == NULL || strlen(newpkg->name) == 0) { + _alpm_log(PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile); + goto pkg_invalid; + } + if(newpkg->version == NULL || strlen(newpkg->version) == 0) { + _alpm_log(PM_LOG_ERROR, _("missing package version in %s\n"), pkgfile); + goto pkg_invalid; + } + config = 1; + continue; + } else if(strcmp(entry_name, ".INSTALL") == 0) { + newpkg->scriptlet = 1; + } else if(*entry_name == '.') { + /* for now, ignore all files starting with '.' that haven't + * already been handled (for future possibilities) */ + } else { + /* Keep track of all files for filelist generation */ + newpkg->files = alpm_list_add(newpkg->files, strdup(entry_name)); + } + + 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; + goto error; + } + + /* if we are not doing a full read, see if we have all we need */ + if(!full && config) { + break; + } + } + + 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; + goto error; + } + + if(!config) { + _alpm_log(PM_LOG_ERROR, _("missing package metadata in %s\n"), pkgfile); + goto pkg_invalid; + } + + archive_read_finish(archive); + + /* internal fields for package struct */ + newpkg->origin = PKG_FROM_FILE; + newpkg->origin_data.file = strdup(pkgfile); + + if(full) { + /* "checking for conflicts" requires a sorted list, ensure that here */ + _alpm_log(PM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile); + newpkg->files = alpm_list_msort(newpkg->files, alpm_list_count(newpkg->files), + _alpm_str_cmp); + newpkg->infolevel = INFRQ_ALL; + } else { + /* get rid of any partial filelist we may have collected, it is invalid */ + FREELIST(newpkg->files); + newpkg->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_DEPENDS; + } + + return(newpkg); + +pkg_invalid: + pm_errno = PM_ERR_PKG_INVALID; +error: + _alpm_pkg_free(newpkg); + archive_read_finish(archive); + + return(NULL); +} + +/** Create a package from a file. + * If full is false, the archive is read only until all necessary + * metadata is found. If it is true, the entire archive is read, which + * serves as a verfication of integrity and the filelist can be created. + * @param filename location of the package tarball + * @param full whether to stop the load after metadata is read or continue + * through the full archive + * @param pkg address of the package pointer + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_pkg_load(const char *filename, unsigned short full, + pmpkg_t **pkg) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(filename != NULL && strlen(filename) != 0, + RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + + *pkg = pkg_load(filename, full); + if(*pkg == NULL) { + /* pm_errno is set by pkg_load */ + return(-1); + } + + return(0); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/cache.c b/lib/libalpm/cache.c index 0ad923a5..b140476c 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" @@ -41,32 +40,21 @@ */ int _alpm_db_load_pkgcache(pmdb_t *db) { - pmpkg_t *info; - int count = 0; - ALPM_LOG_FUNC; if(db == NULL) { return(-1); } - _alpm_db_free_pkgcache(db); _alpm_log(PM_LOG_DEBUG, "loading package cache for repository '%s'\n", - db->treename); - - _alpm_db_rewind(db); - while((info = _alpm_db_scan(db, NULL)) != NULL) { - _alpm_log(PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", - alpm_pkg_get_name(info), db->treename); - info->origin = PKG_FROM_CACHE; - info->origin_data.db = db; - /* add to the collection */ - db->pkgcache = alpm_list_add(db->pkgcache, info); - count++; + db->treename); + if(_alpm_db_populate(db) == -1) { + _alpm_log(PM_LOG_DEBUG, + "failed to load package cache for repository '%s'\n", db->treename); + return(-1); } - db->pkgcache = alpm_list_msort(db->pkgcache, count, _alpm_pkg_cmp); return(0); } @@ -81,10 +69,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 +100,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); @@ -181,7 +160,7 @@ pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target) return(NULL); } - return(_alpm_pkg_find(target, pkgcache)); + return(_alpm_pkg_find(pkgcache, target)); } /* Returns a new group cache from db. @@ -208,33 +187,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 +227,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..a8bcdd59 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) { @@ -416,26 +447,6 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *roo if(!skip_conflict) { _alpm_log(PM_LOG_DEBUG, "checking possible conflict: %s\n", path); - /* Make sure the possible conflict is not a symlink that points to a - * path in the old package. This is kind of dirty with inode usage */ - /* TODO this seems ripe for a cleanup */ - if(dbpkg) { - struct stat pkgbuf; - char str[PATH_MAX+1]; - unsigned ok = 0; - for(k = dbpkg->files; k; k = k->next) { - snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data); - if(!_alpm_lstat(str, &pkgbuf) && lsbuf.st_ino == pkgbuf.st_ino) { - ok = 1; - _alpm_log(PM_LOG_DEBUG, "conflict was a symlink: %s\n", path); - break; - } - } - if(ok == 1) { - continue; - } - } - /* Look at all the targets to see if file has changed hands */ int resolved_conflict = 0; /* have we acted on this conflict? */ for(k = targets; k; k = k->next) { 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..0be81cb1 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -28,7 +28,6 @@ #include <stdlib.h> #include <errno.h> #include <string.h> -#include <stdint.h> /* uintmax_t */ #include <sys/stat.h> #include <dirent.h> #include <regex.h> @@ -39,8 +38,6 @@ #include "alpm_list.h" #include "log.h" #include "util.h" -#include "error.h" -#include "server.h" #include "handle.h" #include "cache.h" #include "alpm.h" @@ -190,14 +187,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); @@ -206,98 +198,6 @@ int SYMEXPORT alpm_db_setserver(pmdb_t *db, const char *url) return(0); } -/** Update a package database - * @param force if true, then forces the update, otherwise update only in case - * the database isn't up to date - * @param db pointer to the package database to update - * @return 0 on success, > 0 on error (pm_errno is set accordingly), < 0 if up - * to date - */ -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; - - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(db != NULL && db != handle->db_local, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - /* Verify we are in a transaction. This is done _mainly_ because we need a DB - * lock - if we update without a db lock, we may kludge some other pacman - * process that _has_ a lock. - */ - ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - ASSERT(handle->trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1)); - - if(!alpm_list_find_ptr(handle->dbs_sync, db)) { - RET_ERR(PM_ERR_DB_NOT_FOUND, -1); - } - - if(!force) { - /* get the lastupdate time */ - lastupdate = _alpm_db_getlastupdate(db); - if(lastupdate == 0) { - _alpm_log(PM_LOG_DEBUG, "failed to get lastupdate time for %s\n", - db->treename); - } - } - - /* 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); - 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); - } 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); - } - snprintf(path, PATH_MAX, "%s%s" DBEXT, dbpath, db->treename); - - /* remove the old dir */ - _alpm_log(PM_LOG_DEBUG, "flushing database %s\n", db->path); - for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { - pmpkg_t *pkg = lp->data; - if(pkg && _alpm_db_remove(db, pkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s%s\n"), db->treename, - alpm_pkg_get_name(pkg)); - RET_ERR(PM_ERR_DB_REMOVE, -1); - } - } - - /* Cache needs to be rebuild */ - _alpm_db_free_pkgcache(db); - - /* uncompress the sync database */ - if(_alpm_db_install(db, path) == -1) { - return -1; - } - } - - return(0); -} - /** Get the name of a package database * @param db pointer to the package database * @return the name of the package database, NULL on error @@ -319,8 +219,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 +227,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); } @@ -367,23 +265,6 @@ alpm_list_t SYMEXPORT *alpm_db_getpkgcache(pmdb_t *db) return(_alpm_db_get_pkgcache(db)); } -/** Get the list of packages that a package provides - * @param db pointer to the package database to get the package from - * @param name name of the package - * @return the list of packages on success, NULL on error - */ -alpm_list_t SYMEXPORT *alpm_db_whatprovides(pmdb_t *db, const char *name) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - ASSERT(name != NULL && strlen(name) != 0, return(NULL)); - - return(_alpm_db_whatprovides(db, name)); -} - /** Get a group entry from a package database * @param db pointer to the package database to get the group from * @param name of the group @@ -445,35 +326,31 @@ 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; } -int _alpm_db_cmp(const void *db1, const void *db2) +int _alpm_db_cmp(const void *d1, const void *d2) { - ALPM_LOG_FUNC; - return(strcmp(((pmdb_t *)db1)->treename, ((pmdb_t *)db2)->treename)); + pmdb_t *db1 = (pmdb_t *)db1; + pmdb_t *db2 = (pmdb_t *)db2; + return(strcmp(db1->treename, db2->treename)); } alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) @@ -500,18 +377,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 @@ -641,47 +516,4 @@ pmdb_t *_alpm_db_register_sync(const char *treename) return(db); } -/* helper function for alpm_list_find and _alpm_db_whatprovides - * - * @return "provision.name" == needle (as string) - */ -int _alpm_prov_cmp(const void *provision, const void *needle) -{ - char *tmpptr; - char *provname = strdup(provision); - int retval = 0; - tmpptr = strchr(provname, '='); - - if(tmpptr != NULL) { /* provision-version */ - *tmpptr='\0'; - } - retval = strcmp(provname, needle); - free(provname); - return(retval); -} - -/* return a alpm_list_t of packages in "db" that provide "package" - */ -alpm_list_t *_alpm_db_whatprovides(pmdb_t *db, const char *package) -{ - alpm_list_t *pkgs = NULL; - alpm_list_t *lp; - - ALPM_LOG_FUNC; - - if(db == NULL || package == NULL || strlen(package) == 0) { - return(NULL); - } - - for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { - pmpkg_t *info = lp->data; - - if(alpm_list_find(alpm_pkg_get_provides(info), (const void *)package, _alpm_prov_cmp)) { - pkgs = alpm_list_add(pkgs, info); - } - } - - return(pkgs); -} - /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 8c8c9bd7..eb0af1ae 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; @@ -55,21 +55,13 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles); pmdb_t *_alpm_db_register_local(void); pmdb_t *_alpm_db_register_sync(const char *treename); -/* Provision */ -int _alpm_prov_cmp(const void *provision, const void *needle); -alpm_list_t *_alpm_db_whatprovides(pmdb_t *db, const char *package); - /* be.c, backend specific calls */ -int _alpm_db_install(pmdb_t *db, const char *dbfile); int _alpm_db_open(pmdb_t *db); void _alpm_db_close(pmdb_t *db); -void _alpm_db_rewind(pmdb_t *db); -pmpkg_t *_alpm_db_scan(pmdb_t *db, const char *target); +int _alpm_db_populate(pmdb_t *db); int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq); int _alpm_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq); int _alpm_db_remove(pmdb_t *db, pmpkg_t *info); -time_t _alpm_db_getlastupdate(const pmdb_t *db); -int _alpm_db_setlastupdate(const pmdb_t *db, time_t time); #endif /* _ALPM_DB_H */ diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 3d33c595..22d9beb4 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); +off_t 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 = LONG_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 off_t 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 == LONG_MAX) { + break; } - FREE(fname); - - dlts = alpm_list_next(dlts); - } + v->state = -1; - return(sum); -} + 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; + } -/** 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; + v->childptr = (v->childptr)->next; - /* 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; + off_t 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 LONG_MAX if path is unfindable */ -alpm_list_t *_alpm_shortest_delta_path(alpm_list_t *deltas, const char *from, - const char *to) +off_t _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; + off_t bestsize = LONG_MAX; - path = shortest_delta_path(deltas, from, to, path); + ALPM_LOG_FUNC; - return(path); + 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); + + _alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete\n"); + + 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'; + STRDUP(delta->from_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + + tmp2 = tmp; + tmp = strchr(tmp, ' '); + *(tmp++) = '\0'; + STRDUP(delta->to, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - strncpy(delta->to, tmp2, DLT_VERSION_LEN); + STRDUP(delta->to_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - delta->size = atol(tmp2); + STRDUP(delta->delta, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - strncpy(delta->filename, tmp2, DLT_FILENAME_LEN); + STRDUP(delta->delta_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); - strncpy(delta->md5sum, tmp, DLT_MD5SUM_LEN); + 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..5bb86b94 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 @@ -19,24 +19,33 @@ #ifndef _ALPM_DELTA_H #define _ALPM_DELTA_H -#include "alpm.h" +#include <sys/types.h> /* off_t */ -#define DLT_FILENAME_LEN 512 -#define DLT_VERSION_LEN 64 -#define DLT_MD5SUM_LEN 33 +#include "alpm.h" 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 */ + off_t delta_size; + /** download filesize of the delta file */ + off_t 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); +off_t _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..37e99162 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); -} - -static void _alpm_graph_free(void *data) -{ - pmgraph_t *graph = data; - alpm_list_free(graph->children); - free(graph); + FREE(dep->name); + FREE(dep->version); + FREE(dep); } -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); @@ -208,10 +194,55 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode) return(newtargs); } -/* Little helper function for alpm_list_find */ -static int satisfycmp(const void *pkg, const void *depend) +alpm_list_t *_alpm_find_dep_satisfiers(alpm_list_t *pkgs, pmdepend_t *dep) { - return(!alpm_depcmp((pmpkg_t*) pkg, (pmdepend_t*) depend)); + alpm_list_t *i, *ret = NULL; + + for(i = pkgs; i; i = alpm_list_next(i)) { + pmpkg_t *pkg = i->data; + if(alpm_depcmp(pkg, dep)) { + ret = alpm_list_add(ret, pkg); + } + } + return(ret); +} + +/** Find packages in a list that provide a given package. + * @param pkgs an alpm_list_t* of package to search + * @param pkgname the name of the package + * @return an alpm_list_t* of packages that provide pkgname + */ +alpm_list_t SYMEXPORT *alpm_find_pkg_satisfiers(alpm_list_t *pkgs, const char *pkgname) +{ + pmdepend_t *dep = _alpm_splitdep(pkgname); + alpm_list_t *res = _alpm_find_dep_satisfiers(pkgs, dep); + _alpm_dep_free(dep); + return(res); +} + +/** 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_find_dep_satisfiers(_alpm_db_get_pkgcache(db), dep)) { + ret = alpm_list_add(ret, target); + } + _alpm_dep_free(dep); + } + return(ret); } /** Checks dependencies and returns missing ones in a list. @@ -257,15 +288,14 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, pmdepend_t *depend = j->data; /* 1. we check the upgrade list */ /* 2. we check database for untouched satisfying packages */ - if(!alpm_list_find(upgrade, depend, satisfycmp) && - !alpm_list_find(dblist, depend, satisfycmp)) { + if(!_alpm_find_dep_satisfiers(upgrade, depend) && + !_alpm_find_dep_satisfiers(dblist, depend)) { /* Unsatisfied dependency in the upgrade list */ char *missdepstring = alpm_dep_get_string(depend); _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 +308,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_getdata(_alpm_find_dep_satisfiers(modified, depend)); /* 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) && - !alpm_list_find(upgrade, depend, satisfycmp) && - !alpm_list_find(dblist, depend, satisfycmp)) { + if(causingpkg && + !_alpm_find_dep_satisfiers(upgrade, depend) && + !_alpm_find_dep_satisfiers(dblist, depend)) { 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); } } @@ -309,7 +339,7 @@ static int dep_vercmp(const char *version1, pmdepmod_t mod, if(mod == PM_DEP_MOD_ANY) { equal = 1; } else { - int cmp = _alpm_versioncmp(version1, version2); + int cmp = alpm_pkg_vercmp(version1, version2); switch(mod) { case PM_DEP_MOD_EQ: equal = (cmp == 0); break; case PM_DEP_MOD_GE: equal = (cmp >= 0); break; @@ -356,7 +386,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 +395,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 +421,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,9 +458,9 @@ 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)) { + if(_alpm_pkg_find(targets, alpm_pkg_get_name(pkg))) { return(0); } @@ -439,15 +480,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(targets, lpkg->name)) { + return(0); + } + break; + } } } - FREELIST(requiredby); /* it's ok to remove */ return(1); @@ -523,7 +566,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,13 +591,15 @@ 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(remove, alpm_pkg_get_name(sync)) + && !_alpm_pkg_find(*list, alpm_pkg_get_name(sync)); if(!found) { continue; } /* If package is in the ignorepkg list, ask before we pull it */ if(_alpm_pkg_should_ignore(sync)) { - pmpkg_t *dummypkg = _alpm_pkg_new(miss->target, NULL); + pmpkg_t *dummypkg = _alpm_pkg_new(); + STRDUP(dummypkg->name, miss->target, RET_ERR(PM_ERR_MEMORY, -1)); QUESTION(trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, dummypkg, sync, NULL, &found); _alpm_pkg_free(dummypkg); } @@ -570,12 +615,14 @@ 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(remove, alpm_pkg_get_name(sync)) + && !_alpm_pkg_find(*list, alpm_pkg_get_name(sync)); if(!found) { continue; } if(_alpm_pkg_should_ignore(sync)) { - pmpkg_t *dummypkg = _alpm_pkg_new(miss->target, NULL); + pmpkg_t *dummypkg = _alpm_pkg_new(); + STRDUP(dummypkg->name, miss->target, RET_ERR(PM_ERR_MEMORY, -1)); QUESTION(trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, dummypkg, sync, NULL, &found); _alpm_pkg_free(dummypkg); } @@ -611,7 +658,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 +675,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 +695,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 +705,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 +715,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 +725,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 +735,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 +743,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 +773,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..70badfd9 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -29,31 +29,29 @@ /* 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); +alpm_list_t *_alpm_find_dep_satisfiers(alpm_list_t *pkgs, pmdepend_t *dep); #endif /* _ALPM_DEPS_H */ diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c new file mode 100644 index 00000000..b5f0b876 --- /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; + size_t 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); + } + + size_t 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; + } + + size_t 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..72a7136f --- /dev/null +++ b/lib/libalpm/graph.h @@ -0,0 +1,58 @@ +/* + * 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 <sys/types.h> /* off_t */ + +#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; + off_t 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..3e080a58 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,20 +50,12 @@ 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); } -/* Helper function for sorting groups - */ -int _alpm_grp_cmp(const void *g1, const void *g2) -{ - pmgrp_t *grp1 = (pmgrp_t *)g1; - pmgrp_t *grp2 = (pmgrp_t *)g2; - - return(strcmp(grp1->name, grp2->name)); -} - const char SYMEXPORT *alpm_grp_get_name(const pmgrp_t *grp) { ALPM_LOG_FUNC; @@ -74,7 +66,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..e261260c 100644 --- a/lib/libalpm/group.h +++ b/lib/libalpm/group.h @@ -19,19 +19,17 @@ #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); #endif /* _ALPM_GROUP_H */ diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 36822285..af1cc78b 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -23,7 +23,6 @@ #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <limits.h> #include <sys/types.h> #include <syslog.h> @@ -36,10 +35,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; @@ -55,8 +52,6 @@ pmhandle_t *_alpm_handle_new() handle->lckfd = -1; handle->logstream = NULL; - /* see if we're root or not */ - handle->uid = geteuid(); handle->root = NULL; handle->dbpath = NULL; handle->cachedirs = NULL; @@ -120,6 +115,15 @@ alpm_cb_download SYMEXPORT alpm_option_get_dlcb() return handle->dlcb; } +alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb() +{ + if (handle == NULL) { + pm_errno = PM_ERR_HANDLE_NULL; + return NULL; + } + return handle->totaldlcb; +} + const char SYMEXPORT *alpm_option_get_root() { if (handle == NULL) { @@ -273,6 +277,15 @@ void SYMEXPORT alpm_option_set_dlcb(alpm_cb_download cb) handle->dlcb = cb; } +void SYMEXPORT alpm_option_set_totaldlcb(alpm_cb_totaldl cb) +{ + if (handle == NULL) { + pm_errno = PM_ERR_HANDLE_NULL; + return; + } + handle->totaldlcb = cb; +} + int SYMEXPORT alpm_option_set_root(const char *root) { struct stat st; @@ -386,7 +399,7 @@ void SYMEXPORT alpm_option_set_cachedirs(alpm_list_t *cachedirs) int SYMEXPORT alpm_option_remove_cachedir(const char *cachedir) { - void *vdata = NULL; + char *vdata = NULL; char *newcachedir; size_t cachedirlen; /* verify cachedir ends in a '/' */ @@ -397,8 +410,7 @@ int SYMEXPORT alpm_option_remove_cachedir(const char *cachedir) newcachedir = calloc(cachedirlen + 1, sizeof(char)); strncpy(newcachedir, cachedir, cachedirlen); newcachedir[cachedirlen-1] = '/'; - handle->cachedirs = alpm_list_remove(handle->cachedirs, newcachedir, - _alpm_str_cmp, &vdata); + handle->cachedirs = alpm_list_remove_str(handle->cachedirs, newcachedir, &vdata); FREE(newcachedir); if(vdata != NULL) { FREE(vdata); @@ -451,9 +463,8 @@ void SYMEXPORT alpm_option_set_noupgrades(alpm_list_t *noupgrade) int SYMEXPORT alpm_option_remove_noupgrade(const char *pkg) { - void *vdata = NULL; - handle->noupgrade = alpm_list_remove(handle->noupgrade, pkg, - _alpm_str_cmp, &vdata); + char *vdata = NULL; + handle->noupgrade = alpm_list_remove_str(handle->noupgrade, pkg, &vdata); if(vdata != NULL) { FREE(vdata); return(1); @@ -474,9 +485,8 @@ void SYMEXPORT alpm_option_set_noextracts(alpm_list_t *noextract) int SYMEXPORT alpm_option_remove_noextract(const char *pkg) { - void *vdata = NULL; - handle->noextract = alpm_list_remove(handle->noextract, pkg, - _alpm_str_cmp, &vdata); + char *vdata = NULL; + handle->noextract = alpm_list_remove_str(handle->noextract, pkg, &vdata); if(vdata != NULL) { FREE(vdata); return(1); @@ -497,9 +507,8 @@ void SYMEXPORT alpm_option_set_ignorepkgs(alpm_list_t *ignorepkgs) int SYMEXPORT alpm_option_remove_ignorepkg(const char *pkg) { - void *vdata = NULL; - handle->ignorepkg = alpm_list_remove(handle->ignorepkg, pkg, - _alpm_str_cmp, &vdata); + char *vdata = NULL; + handle->ignorepkg = alpm_list_remove_str(handle->ignorepkg, pkg, &vdata); if(vdata != NULL) { FREE(vdata); return(1); @@ -520,9 +529,8 @@ void SYMEXPORT alpm_option_set_holdpkgs(alpm_list_t *holdpkgs) int SYMEXPORT alpm_option_remove_holdpkg(const char *pkg) { - void *vdata = NULL; - handle->holdpkg = alpm_list_remove(handle->holdpkg, pkg, - _alpm_str_cmp, &vdata); + char *vdata = NULL; + handle->holdpkg = alpm_list_remove_str(handle->holdpkg, pkg, &vdata); if(vdata != NULL) { FREE(vdata); return(1); @@ -543,9 +551,8 @@ void SYMEXPORT alpm_option_set_ignoregrps(alpm_list_t *ignoregrps) int SYMEXPORT alpm_option_remove_ignoregrp(const char *grp) { - void *vdata = NULL; - handle->ignoregrp = alpm_list_remove(handle->ignoregrp, grp, - _alpm_str_cmp, &vdata); + char *vdata = NULL; + handle->ignoregrp = alpm_list_remove_str(handle->ignoregrp, grp, &vdata); if(vdata != NULL) { FREE(vdata); return(1); diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index 5051917e..bec0a6f1 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -30,7 +30,6 @@ typedef struct _pmhandle_t { /* internal usage */ - uid_t uid; /* current UID */ /* TODO is this used? */ pmdb_t *db_local; /* local db pointer */ alpm_list_t *dbs_sync; /* List of (pmdb_t *) */ FILE *logstream; /* log file stream pointer */ @@ -40,6 +39,7 @@ typedef struct _pmhandle_t { /* callback functions */ alpm_cb_log logcb; /* Log callback function */ alpm_cb_download dlcb; /* Download callback function */ + alpm_cb_totaldl totaldlcb; /* Total download callback function */ /* filesystem paths */ char *root; /* Root path, default '/' */ @@ -50,7 +50,7 @@ typedef struct _pmhandle_t { /* package lists */ alpm_list_t *noupgrade; /* List of packages NOT to be upgraded */ - alpm_list_t *noextract; /* List of packages NOT to extract */ /*TODO is this used?*/ + alpm_list_t *noextract; /* List of files NOT to extract */ alpm_list_t *ignorepkg; /* List of packages to ignore */ alpm_list_t *holdpkg; /* List of packages which 'hold' pacman */ alpm_list_t *ignoregrp; /* List of groups to ignore */ 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/md5.c b/lib/libalpm/md5.c index 4c903895..413af3f3 100644 --- a/lib/libalpm/md5.c +++ b/lib/libalpm/md5.c @@ -3,18 +3,18 @@ * * Copyright (C) 2006-2007 Christophe Devine * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License, version 2.1 as published by the Free Software Foundation. + * 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 library is distributed in the hope that it will be useful, + * 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 - * Lesser General Public License for more details. + * 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 Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * The MD5 algorithm was designed by Ron Rivest in 1991. @@ -25,8 +25,9 @@ * Pacman Notes: * * Taken from the XySSL project at www.xyssl.org under terms of the - * LGPL. This is from version 0.7 of the library, and has been modified + * GPL. This is from version 0.9 of the library, and has been modified * as following, which may be helpful for future updates: + * * remove "xyssl/config.h" include * * change include from "xyssl/md5.h" to "md5.h" * * removal of HMAC code * * removal of SELF_TEST code @@ -35,12 +36,9 @@ * int md5_file( char *path, unsigned char *output ) * to * int md5_file( const char *path, unsigned char *output ) + * * various static/inline changes */ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - #include <string.h> #include <stdio.h> @@ -49,8 +47,8 @@ /* * 32-bit integer manipulation macros (little endian) */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ { \ (n) = ( (unsigned long) (b)[(i) ] ) \ | ( (unsigned long) (b)[(i) + 1] << 8 ) \ @@ -59,8 +57,8 @@ } #endif -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ { \ (b)[(i) ] = (unsigned char) ( (n) ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ @@ -87,22 +85,22 @@ static inline void md5_process( md5_context *ctx, unsigned char data[64] ) { unsigned long X[16], A, B, C, D; - GET_UINT32_LE( X[ 0], data, 0 ); - GET_UINT32_LE( X[ 1], data, 4 ); - GET_UINT32_LE( X[ 2], data, 8 ); - GET_UINT32_LE( X[ 3], data, 12 ); - GET_UINT32_LE( X[ 4], data, 16 ); - GET_UINT32_LE( X[ 5], data, 20 ); - GET_UINT32_LE( X[ 6], data, 24 ); - GET_UINT32_LE( X[ 7], data, 28 ); - GET_UINT32_LE( X[ 8], data, 32 ); - GET_UINT32_LE( X[ 9], data, 36 ); - GET_UINT32_LE( X[10], data, 40 ); - GET_UINT32_LE( X[11], data, 44 ); - GET_UINT32_LE( X[12], data, 48 ); - GET_UINT32_LE( X[13], data, 52 ); - GET_UINT32_LE( X[14], data, 56 ); - GET_UINT32_LE( X[15], data, 60 ); + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) @@ -250,7 +248,7 @@ static inline void md5_update( md5_context *ctx, unsigned char *input, int ilen } } -static unsigned char md5_padding[64] = +static const unsigned char md5_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -261,7 +259,7 @@ static unsigned char md5_padding[64] = /* * MD5 final digest */ -static inline void md5_finish( md5_context *ctx, unsigned char *output ) +static inline void md5_finish( md5_context *ctx, unsigned char output[16] ) { unsigned long last, padn; unsigned long high, low; @@ -271,8 +269,8 @@ static inline void md5_finish( md5_context *ctx, unsigned char *output ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); @@ -280,17 +278,16 @@ static inline void md5_finish( md5_context *ctx, unsigned char *output ) md5_update( ctx, (unsigned char *) md5_padding, padn ); md5_update( ctx, msglen, 8 ); - PUT_UINT32_LE( ctx->state[0], output, 0 ); - PUT_UINT32_LE( ctx->state[1], output, 4 ); - PUT_UINT32_LE( ctx->state[2], output, 8 ); - PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); } /* - * Output = MD5( input buffer ) + * output = MD5( input buffer ) */ -void md5( unsigned char *input, int ilen, - unsigned char *output ) +void md5( unsigned char *input, int ilen, unsigned char output[16] ) { md5_context ctx; @@ -302,9 +299,9 @@ void md5( unsigned char *input, int ilen, } /* - * Output = MD5( file contents ) + * output = MD5( file contents ) */ -int md5_file( const char *path, unsigned char *output ) +int md5_file( const char *path, unsigned char output[16] ) { FILE *f; size_t n; diff --git a/lib/libalpm/md5.h b/lib/libalpm/md5.h index d206e463..ddcea8c7 100644 --- a/lib/libalpm/md5.h +++ b/lib/libalpm/md5.h @@ -3,29 +3,24 @@ * * Copyright (C) 2006-2007 Christophe Devine * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License, version 2.1 as published by the Free Software Foundation. + * 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 library is distributed in the hope that it will be useful, + * 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 - * Lesser General Public License for more details. + * 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 Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. + * 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 _MD5_H #define _MD5_H -#ifdef __cplusplus -extern "C" { -#endif - /** - * \internal * \brief MD5 context structure */ typedef struct @@ -37,18 +32,15 @@ typedef struct md5_context; /** - * \internal * \brief Output = MD5( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output MD5 checksum result */ -void md5( unsigned char *input, int ilen, - unsigned char *output ); +void md5( unsigned char *input, int ilen, unsigned char output[16] ); /** - * \internal * \brief Output = MD5( file contents ) * * \param path input file name @@ -57,10 +49,6 @@ void md5( unsigned char *input, int ilen, * \return 0 if successful, 1 if fopen failed, * or 2 if fread failed */ -int md5_file( const char *path, unsigned char *output ); - -#ifdef __cplusplus -} -#endif +int md5_file( const char *path, unsigned char output[16] ); #endif /* md5.h */ diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 794a2f7d..3708a58a 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -31,7 +31,6 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> -#include <locale.h> /* setlocale */ /* libarchive */ #include <archive.h> @@ -42,7 +41,6 @@ #include "alpm_list.h" #include "log.h" #include "util.h" -#include "error.h" #include "db.h" #include "cache.h" #include "delta.h" @@ -54,42 +52,13 @@ * @{ */ -/** Create a package from a file. - * If full is false, the archive is read only until all necessary - * metadata is found. If it is true, the entire archive is read, which - * serves as a verfication of integrity and the filelist can be created. - * @param filename location of the package tarball - * @param full whether to stop the load after metadata is read or continue - * through the full archive - * @param pkg address of the package pointer - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_pkg_load(const char *filename, unsigned short full, - pmpkg_t **pkg) -{ - _alpm_log(PM_LOG_FUNCTION, "enter alpm_pkg_load\n"); - - /* Sanity checks */ - ASSERT(filename != NULL && strlen(filename) != 0, - RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - - *pkg = _alpm_pkg_load(filename, full); - if(*pkg == NULL) { - /* pm_errno is set by pkg_load */ - return(-1); - } - - return(0); -} - /** Free a package. * @param pkg package pointer to free * @return 0 on success, -1 on error (pm_errno is set accordingly) */ int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg) { - _alpm_log(PM_LOG_FUNCTION, "enter alpm_pkg_free\n"); + ALPM_LOG_FUNC; ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); @@ -108,8 +77,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; @@ -119,44 +87,19 @@ 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); } -/** Compare versions. - * @param ver1 first version - * @param ver2 secont version - * @return postive, 0 or negative if ver1 is less, equal or more - * than ver2, respectively. - */ -int SYMEXPORT alpm_pkg_vercmp(const char *ver1, const char *ver2) -{ - ALPM_LOG_FUNC; - - return(_alpm_versioncmp(ver1, ver2)); -} - const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -169,45 +112,18 @@ 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; } const char SYMEXPORT *alpm_pkg_get_name(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_CACHE && !(pkg->infolevel & INFRQ_BASE)) { - _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_BASE); - } return pkg->name; } const char SYMEXPORT *alpm_pkg_get_version(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_CACHE && !(pkg->infolevel & INFRQ_BASE)) { - _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_BASE); - } return pkg->version; } @@ -309,7 +225,7 @@ const char SYMEXPORT *alpm_pkg_get_arch(pmpkg_t *pkg) return pkg->arch; } -unsigned long SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) +off_t SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -323,7 +239,7 @@ unsigned long SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) return pkg->size; } -unsigned long SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg) +off_t SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -523,7 +439,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); @@ -650,108 +566,178 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg) return(reqs); } -/** @} */ - -/* this function was taken from rpm 4.0.4 and rewritten */ -int _alpm_versioncmp(const char *a, const char *b) +/** Compare two version strings and determine which one is 'newer'. + * Returns a value comparable to the way strcmp works. Returns 1 + * if a is newer than b, 0 if a and b are the same version, or -1 + * if b is newer than a. + * + * This function has been adopted from the rpmvercmp function located + * at lib/rpmvercmp.c, and was most recently updated against rpm + * version 4.4.2.3. Small modifications have been made to make it more + * consistent with the libalpm coding style. + * + * Keep in mind that the pkgrel is only compared if it is available + * on both versions handed to this function. For example, comparing + * 1.5-1 and 1.5 will yield 0; comparing 1.5-1 and 1.5-2 will yield + * -1 as expected. This is mainly for supporting versioned dependencies + * that do not include the pkgrel. + */ +int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) { - char str1[64], str2[64]; + char oldch1, oldch2; + char *str1, *str2; char *ptr1, *ptr2; char *one, *two; - char *rel1 = NULL, *rel2 = NULL; - char oldch1, oldch2; - int is1num, is2num; int rc; + int isnum; + int ret = 0; ALPM_LOG_FUNC; - if(!strcmp(a,b)) { - return(0); + /* libalpm added code. ensure our strings are not null */ + if(!a) { + if(!b) return(0); + return(-1); } + if(!b) return(1); - strncpy(str1, a, 64); - str1[63] = 0; - strncpy(str2, b, 64); - str2[63] = 0; + /* easy comparison to see if versions are identical */ + if(strcmp(a, b) == 0) return(0); - /* lose the release number */ - for(one = str1; *one && *one != '-'; one++); - if(one) { - *one = '\0'; - rel1 = ++one; - } - for(two = str2; *two && *two != '-'; two++); - if(two) { - *two = '\0'; - rel2 = ++two; - } + str1 = strdup(a); + str2 = strdup(b); one = str1; two = str2; - while(*one || *two) { + /* loop through each version segment of str1 and str2 and compare them */ + while(*one && *two) { while(*one && !isalnum((int)*one)) one++; while(*two && !isalnum((int)*two)) two++; + /* If we ran to the end of either, we are finished with the loop */ + if(!(*one && *two)) break; + ptr1 = one; ptr2 = two; - /* find the next segment for each string */ + /* grab first completely alpha or completely numeric segment */ + /* leave one and two pointing to the start of the alpha or numeric */ + /* segment and walk ptr1 and ptr2 to end of segment */ if(isdigit((int)*ptr1)) { - is1num = 1; while(*ptr1 && isdigit((int)*ptr1)) ptr1++; - } else { - is1num = 0; - while(*ptr1 && isalpha((int)*ptr1)) ptr1++; - } - if(isdigit((int)*ptr2)) { - is2num = 1; while(*ptr2 && isdigit((int)*ptr2)) ptr2++; + isnum = 1; } else { - is2num = 0; + while(*ptr1 && isalpha((int)*ptr1)) ptr1++; while(*ptr2 && isalpha((int)*ptr2)) ptr2++; + isnum = 0; } + /* save character at the end of the alpha or numeric segment */ + /* so that they can be restored after the comparison */ oldch1 = *ptr1; *ptr1 = '\0'; oldch2 = *ptr2; *ptr2 = '\0'; - /* see if we ran out of segments on one string */ - if(one == ptr1 && two != ptr2) { - return(is2num ? -1 : 1); + /* this cannot happen, as we previously tested to make sure that */ + /* the first string has a non-null segment */ + if (one == ptr1) { + ret = -1; /* arbitrary */ + goto cleanup; } - if(one != ptr1 && two == ptr2) { - return(is1num ? 1 : -1); + + /* take care of the case where the two version segments are */ + /* different types: one numeric, the other alpha (i.e. empty) */ + /* numeric segments are always newer than alpha segments */ + /* XXX See patch #60884 (and details) from bugzilla #50977. */ + if (two == ptr2) { + ret = isnum ? 1 : -1; + goto cleanup; } - /* see if we have a type mismatch (ie, one is alpha and one is digits) */ - if(is1num && !is2num) return(1); - if(!is1num && is2num) return(-1); + if (isnum) { + /* this used to be done by converting the digit segments */ + /* to ints using atoi() - it's changed because long */ + /* digit segments can overflow an int - this should fix that. */ - if(is1num) while(*one == '0') one++; - if(is2num) while(*two == '0') two++; + /* throw away any leading zeros - it's a number, right? */ + while (*one == '0') one++; + while (*two == '0') two++; - rc = strverscmp(one, two); - if(rc) return(rc); + /* whichever number has more digits wins */ + if (strlen(one) > strlen(two)) { + ret = 1; + goto cleanup; + } + if (strlen(two) > strlen(one)) { + ret = -1; + goto cleanup; + } + } + /* strcmp will return which one is greater - even if the two */ + /* segments are alpha or if they are numeric. don't return */ + /* if they are equal because there might be more segments to */ + /* compare */ + rc = strcmp(one, two); + if (rc) { + ret = rc < 1 ? -1 : 1; + goto cleanup; + } + + /* restore character that was replaced by null above */ *ptr1 = oldch1; - *ptr2 = oldch2; one = ptr1; + *ptr2 = oldch2; two = ptr2; + + /* libalpm added code. check if version strings have hit the pkgrel + * portion. depending on which strings have hit, take correct action. + * this is all based on the premise that we only have one dash in + * the version string, and it separates pkgver from pkgrel. */ + if(*ptr1 == '-' && *ptr2 == '-') { + /* no-op, continue comparing since we are equivalent throughout */ + } else if(*ptr1 == '-') { + /* ptr1 has hit the pkgrel and ptr2 has not. + * version 2 is newer iff we are not at the end of ptr2; + * if we are at end then one version had pkgrel and one did not */ + ret = *ptr2 ? -1 : 0; + goto cleanup; + } else if(*ptr2 == '-') { + /* ptr2 has hit the pkgrel and ptr1 has not. + * version 1 is newer iff we are not at the end of ptr1; + * if we are at end then one version had pkgrel and one did not */ + ret = *ptr1 ? 1 : 0; + goto cleanup; + } } - if((!*one) && (!*two)) { - /* compare release numbers */ - if(rel1 && rel2 && strlen(rel1) && strlen(rel2)) return(_alpm_versioncmp(rel1, rel2)); - return(0); + /* this catches the case where all numeric and alpha segments have */ + /* compared identically but the segment separating characters were */ + /* different */ + if ((!*one) && (!*two)) { + ret = 0; + goto cleanup; + } + + /* whichever version still has characters left over wins */ + if (!*one) { + ret = -1; + } else { + ret = 1; } - return(*one ? 1 : -1); +cleanup: + free(str1); + free(str2); + return(ret); } +/** @} */ -pmpkg_t *_alpm_pkg_new(const char *name, const char *version) +pmpkg_t *_alpm_pkg_new(void) { pmpkg_t* pkg; @@ -759,47 +745,56 @@ 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(version && version[0] != 0) { - strncpy(pkg->version, version, PKG_VERSION_LEN); - } else { - pkg->version[0] = '\0'; - } - return(pkg); } 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); } @@ -812,16 +807,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); } @@ -841,7 +848,7 @@ int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg) } /* compare versions and see if we need to upgrade */ - cmp = _alpm_versioncmp(alpm_pkg_get_version(pkg), alpm_pkg_get_version(local_pkg)); + cmp = alpm_pkg_vercmp(alpm_pkg_get_version(pkg), alpm_pkg_get_version(local_pkg)); if(cmp != 0 && pkg->force) { cmp = 1; @@ -863,269 +870,15 @@ int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg) */ int _alpm_pkg_cmp(const void *p1, const void *p2) { - pmpkg_t *pk1 = (pmpkg_t *)p1; - pmpkg_t *pk2 = (pmpkg_t *)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 - * Returns: 0 on success, 1 on error - * - */ -static int parse_descfile(const char *descfile, pmpkg_t *info) -{ - FILE* fp = NULL; - char line[PATH_MAX]; - char *ptr = NULL; - char *key = NULL; - int linenum = 0; - - 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); - linenum++; - _alpm_strtrim(line); - if(strlen(line) == 0 || line[0] == '#') { - continue; - } - ptr = line; - 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); - } else { - _alpm_strtrim(key); - _alpm_strtrim(ptr); - if(!strcmp(key, "pkgname")) { - strncpy(info->name, ptr, sizeof(info->name)); - } else if(!strcmp(key, "pkgver")) { - strncpy(info->version, ptr, sizeof(info->version)); - } else if(!strcmp(key, "pkgdesc")) { - strncpy(info->desc, ptr, sizeof(info->desc)); - } 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)); - } 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 - setlocale(LC_TIME, "C"); - strptime(ptr, "%a %b %e %H:%M:%S %Y", &tmp_tm); - info->builddate = mktime(&tmp_tm); - setlocale(LC_TIME, ""); - } else { - info->builddate = atol(ptr); - } - } else if(!strcmp(key, "packager")) { - strncpy(info->packager, ptr, sizeof(info->packager)); - } else if(!strcmp(key, "arch")) { - strncpy(info->arch, ptr, sizeof(info->arch)); - } 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); - info->depends = alpm_list_add(info->depends, dep); - } else if(!strcmp(key, "optdepend")) { - info->optdepends = alpm_list_add(info->optdepends, strdup(ptr)); - } else if(!strcmp(key, "conflict")) { - info->conflicts = alpm_list_add(info->conflicts, strdup(ptr)); - } else if(!strcmp(key, "replaces")) { - info->replaces = alpm_list_add(info->replaces, strdup(ptr)); - } else if(!strcmp(key, "provides")) { - info->provides = alpm_list_add(info->provides, strdup(ptr)); - } else if(!strcmp(key, "backup")) { - 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); - } - } - line[0] = '\0'; - } - fclose(fp); - unlink(descfile); - - return(0); -} - - -/** - * Load a package and create the corresponding pmpkg_t struct. - * @param pkgfile path to the package file - * @param full whether to stop the load after metadata is read or continue - * through the full archive - * @return An information filled pmpkg_t struct - */ -pmpkg_t *_alpm_pkg_load(const char *pkgfile, unsigned short full) -{ - int ret = ARCHIVE_OK; - int config = 0; - struct archive *archive; - struct archive_entry *entry; - pmpkg_t *info = NULL; - char *descfile = NULL; - int fd = -1; - struct stat st; - - ALPM_LOG_FUNC; - - if(pkgfile == NULL || strlen(pkgfile) == 0) { - RET_ERR(PM_ERR_WRONG_ARGS, NULL); - } - - if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE_ERROR, NULL); - } - - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - - if (archive_read_open_filename(archive, pkgfile, - ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); - } - - info = _alpm_pkg_new(NULL, NULL); - if(info == NULL) { - archive_read_finish(archive); - RET_ERR(PM_ERR_MEMORY, NULL); - } - - if(stat(pkgfile, &st) == 0) { - 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) { - _alpm_log(PM_LOG_ERROR, _("could not parse package description file in %s\n"), - pkgfile); - goto pkg_invalid; - } - if(!strlen(info->name)) { - _alpm_log(PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile); - goto pkg_invalid; - } - if(!strlen(info->version)) { - _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; - } else if(*entry_name == '.') { - /* for now, ignore all files starting with '.' that haven't - * already been handled (for future possibilities) */ - } else { - /* Keep track of all files for filelist generation */ - info->files = alpm_list_add(info->files, strdup(entry_name)); - } - - 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; - goto error; - } - - /* if we are not doing a full read, see if we have all we need */ - if(!full && config) { - break; - } - } - - 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; - goto error; - } - - if(!config) { - _alpm_log(PM_LOG_ERROR, _("missing package metadata in %s\n"), pkgfile); - goto pkg_invalid; - } - - archive_read_finish(archive); - - /* internal fields for package struct */ - info->origin = PKG_FROM_FILE; - info->origin_data.file = strdup(pkgfile); - - if(full) { - /* "checking for conflicts" requires a sorted list, so we 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 */ - FREELIST(info->files); - info->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_DEPENDS; - } - - return(info); - -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); - - return(NULL); + pmpkg_t *pkg1 = (pmpkg_t *)p1; + pmpkg_t *pkg2 = (pmpkg_t *)p2; + return(strcmp(alpm_pkg_get_name(pkg1), alpm_pkg_get_name(pkg2))); } /* Test for existence of a package in a alpm_list_t* * of pmpkg_t* */ -pmpkg_t *_alpm_pkg_find(const char *needle, alpm_list_t *haystack) +pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) { alpm_list_t *lp; diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index d6c3eff9..d06cf150 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -23,7 +23,8 @@ #ifndef _ALPM_PACKAGE_H #define _ALPM_PACKAGE_H -#include <time.h> +#include <sys/types.h> /* off_t */ +#include <time.h> /* time_t */ #include "alpm.h" #include "db.h" @@ -33,32 +34,20 @@ 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]; - unsigned long size; - unsigned long isize; + char *packager; + char *md5sum; + char *arch; + off_t size; + off_t isize; + off_t download_size; unsigned short scriptlet; unsigned short force; pmpkgreason_t reason; @@ -72,6 +61,7 @@ struct __pmpkg_t { alpm_list_t *conflicts; alpm_list_t *provides; alpm_list_t *deltas; + alpm_list_t *delta_path; /* internal */ pmpkgfrom_t origin; /* Replaced 'void *data' with this union as follows: @@ -85,14 +75,12 @@ struct __pmpkg_t { pmdbinfrq_t infolevel; }; -int _alpm_versioncmp(const char *a, const char *b); -pmpkg_t* _alpm_pkg_new(const char *name, const char *version); +pmpkg_t* _alpm_pkg_new(void); 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_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); +pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle); int _alpm_pkg_should_ignore(pmpkg_t *pkg); #endif /* _ALPM_PACKAGE_H */ diff --git a/lib/libalpm/po/POTFILES.in b/lib/libalpm/po/POTFILES.in index 80130f24..475cf4b4 100644 --- a/lib/libalpm/po/POTFILES.in +++ b/lib/libalpm/po/POTFILES.in @@ -1,23 +1,26 @@ # List of source files with translatable strings +# If a file is commented out, it is because it shouldn't have any +# translatable strings lib/libalpm/add.c lib/libalpm/alpm.c -lib/libalpm/alpm_list.c +#lib/libalpm/alpm_list.c lib/libalpm/backup.c lib/libalpm/be_files.c +lib/libalpm/be_package.c lib/libalpm/cache.c 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 lib/libalpm/log.c -lib/libalpm/md5.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/po/es.po b/lib/libalpm/po/es.po index 71aa1d72..10d58187 100644 --- a/lib/libalpm/po/es.po +++ b/lib/libalpm/po/es.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: es\n" "Report-Msgid-Bugs-To: pacman-dev@archlinux.org\n" -"POT-Creation-Date: 2008-03-03 20:03-0600\n" -"PO-Revision-Date: 2008-01-16 16:04-0300\n" +"POT-Creation-Date: 2008-06-12 17:12-0400\n" +"PO-Revision-Date: 2008-06-12 17:20-0400\n" "Last-Translator: Juan Pablo Gonzalez <jotapesan@gmail.com>\n" "Language-Team: <es@li.org>\n" "MIME-Version: 1.0\n" @@ -18,13 +18,11 @@ msgstr "" #, c-format msgid "replacing older version %s-%s by %s in target list\n" -msgstr "" -"reemplazando la versión antigua %s-%s por %s en la lista de objetivos\n" +msgstr "reemplazando la versión antigua %s-%s por %s en la lista de objetivos\n" #, c-format -msgid "newer version %s-%s is in the target list -- skipping\n" -msgstr "" -"una nueva versión %s-%s esta en la lista de objetivos list -- saltándola\n" +msgid "skipping %s-%s because newer version %s is in the target list\n" +msgstr "saltando %s-%s debido a que una nueva versión de %s esta en la lista\n" #, c-format msgid "conflicting packages were found in the target list\n" @@ -37,8 +35,8 @@ msgstr "" "entre si\n" #, c-format -msgid "replacing packages with -A and -U is not supported yet\n" -msgstr "el reemplazo de paquetes con -A y -U aún no esta soportado\n" +msgid "replacing packages with -U is not supported yet\n" +msgstr "reemplazar paquetes con -U aún no esta soportado\n" #, c-format msgid "you can replace packages manually using -Rd and -U\n" @@ -65,20 +63,16 @@ msgid "could not extract %s (%s)\n" msgstr "no se pudo extraer %s (%s)\n" #, c-format -msgid "could not rename %s (%s)\n" -msgstr "no se pudo renombrar %s (%s)\n" - -#, c-format -msgid "could not copy tempfile to %s (%s)\n" -msgstr "no se pudo copiar el archivo temporal a %s (%s)\n" +msgid "could not rename %s to %s (%s)\n" +msgstr "no se pudo renombrar %s a %s (%s)\n" #, c-format msgid "%s saved as %s\n" msgstr "%s guardado como %s\n" #, c-format -msgid "could not install %s as %s: %s\n" -msgstr "no se pudo instalar %s como %s: %s\n" +msgid "could not install %s as %s (%s)\n" +msgstr "no se pudo instalar %s como %s (%s)\n" #, c-format msgid "%s installed as %s\n" @@ -109,16 +103,28 @@ msgid "could not add entry '%s' in cache\n" msgstr "no se pudo agregar '%s' en la cache\n" #, c-format +msgid "could not remove database entry %s%s\n" +msgstr "no se pudo quitar la entrada %s%s en la base de datos\n" + +#, c-format msgid "invalid name for database entry '%s'\n" msgstr "nombre invalido para la entrada de la base de datos '%s'\n" #, c-format +msgid "corrupted database entry '%s'\n" +msgstr "entrada corrupta en la base de datos '%s'\n" + +#, c-format msgid "could not open file %s: %s\n" msgstr "no se pudo abrir el archivo %s: %s\n" #, c-format -msgid "could not remove database entry %s%s\n" -msgstr "no se pudo quitar la entrada %s%s en la base de datos\n" +msgid "%s database is inconsistent: name mismatch on package %s\n" +msgstr "la base de datos %s es inconsistente: nombre mal emparejado en el paquete %s\n" + +#, c-format +msgid "%s database is inconsistent: version mismatch on package %s\n" +msgstr "la base de datos %s es inconsistente: versión mal emparejada en el paquete %s\n" #, c-format msgid "attempt to re-register the 'local' DB\n" @@ -145,6 +151,50 @@ msgid "cannot resolve \"%s\", a dependency of \"%s\"\n" msgstr "no se pudo resolver \"%s\", una dependencia para \"%s\"\n" #, c-format +msgid "url '%s' is invalid\n" +msgstr "la url %s no es válida\n" + +#, c-format +msgid "url scheme not specified, assuming HTTP\n" +msgstr "no fue especificado el esquema de url, asumiendo HTTP\n" + +#, c-format +msgid "disk" +msgstr "disco" + +#, c-format +msgid "failed retrieving file '%s' from %s : %s\n" +msgstr "fallo al obtener archivo '%s' desde %s: %s\n" + +#, c-format +msgid "cannot resume download, starting over\n" +msgstr "no se puede resumir la descarga, empezando de nuevo\n" + +#, c-format +msgid "cannot write to file '%s'\n" +msgstr "no se pudo escribir al archivo '%s'\n" + +#, c-format +msgid "error downloading '%s': %s\n" +msgstr "error descargando %s: %s\n" + +#, c-format +msgid "error writing to file '%s': %s\n" +msgstr "no se pudo escribir al archivo '%s': %s\n" + +#, c-format +msgid "could not chdir to %s\n" +msgstr "no se pudo cambiar el directorio a %s\n" + +#, c-format +msgid "running XferCommand: fork failed!\n" +msgstr "ejecutando XferCommand: fallo en el fork\n" + +#, c-format +msgid "failed to download %s\n" +msgstr "no se pudo descargar %s\n" + +#, c-format msgid "out of memory!" msgstr "no hay memoria!" @@ -213,10 +263,6 @@ msgid "invalid url for server" msgstr "dirección inválida para el servidor" #, c-format -msgid "could not set parameter" -msgstr "no se pudo fijar el parámetro" - -#, c-format msgid "transaction already initialized" msgstr "la operación ya se inicializó" @@ -265,10 +311,6 @@ msgid "cannot load package data" msgstr "no se pudo cargar la información del paquete" #, c-format -msgid "package already installed" -msgstr "el paquete ya está instalado" - -#, c-format msgid "package not installed or lesser version" msgstr "el paquete no está instalado o es una versión menor" @@ -277,20 +319,16 @@ msgid "cannot remove all files for package" msgstr "no se pudo quitar todos los archivos del paquete" #, c-format -msgid "package name is not valid" -msgstr "el nombre del paquete no es válido" - -#, c-format -msgid "corrupted package" -msgstr "paquete corrupto" +msgid "package filename is not valid" +msgstr "nombre de archivo del paquete no es válido" #, c-format msgid "no such repository" msgstr "no existe el repositorio" #, c-format -msgid "corrupted delta" -msgstr "delta corrupto" +msgid "invalid or corrupted delta" +msgstr "invalido o diferencial corrupto" #, c-format msgid "delta patch failed" @@ -321,10 +359,6 @@ msgid "internal error" msgstr "error interno" #, c-format -msgid "libarchive error" -msgstr "error de libarchive" - -#, c-format msgid "not confirmed" msgstr "no confirmado" @@ -333,20 +367,20 @@ msgid "invalid regular expression" msgstr "expresión regular inválida" #, c-format -msgid "connection to remote host failed" -msgstr "falló la conexión con el host remoto" +msgid "libarchive error" +msgstr "error de libarchive" #, c-format -msgid "unexpected error" -msgstr "error inesperado" +msgid "download library error" +msgstr "error de descarga de librería" #, c-format -msgid "could not get md5sum for package %s-%s\n" -msgstr "no se pudo obtener la verificación md5 para %s-%s\n" +msgid "error invoking external downloader" +msgstr "error invocando el descargador externo" #, c-format -msgid "md5sums do not match for package %s-%s\n" -msgstr "la verificación md5 para el paquete %s-%s no concuerda\n" +msgid "unexpected error" +msgstr "error inesperado" #, c-format msgid "%s: forcing upgrade to version %s\n" @@ -357,30 +391,6 @@ msgid "%s: local (%s) is newer than %s (%s)\n" msgstr "%s: local (%s) es más nuevo que %s (%s)\n" #, c-format -msgid "error extracting package description file to %s\n" -msgstr "error descomprimiendo el paquete de descripción a %s\n" - -#, c-format -msgid "could not parse package description file in %s\n" -msgstr "no se pudo interpretar el archivo de descripción en %s\n" - -#, c-format -msgid "missing package name in %s\n" -msgstr "nombre de paquete perdido en %s\n" - -#, c-format -msgid "missing package version in %s\n" -msgstr "versión de paquete perdida en %s\n" - -#, c-format -msgid "error while reading package %s: %s\n" -msgstr "error mientras se leía el paquete %s: %s\n" - -#, c-format -msgid "missing package metadata in %s\n" -msgstr "faltan los metadatos del paquete en %s\n" - -#, c-format msgid "could not find %s in database -- skipping\n" msgstr "no se pudo encontrar %s en la base de datos -- saltando\n" @@ -397,54 +407,6 @@ msgid "could not remove entry '%s' from cache\n" msgstr "no se pudo quitar la entrada '%s' de la cache\n" #, c-format -msgid "url '%s' is invalid, ignoring\n" -msgstr "la url %s no es válida, ignorando\n" - -#, c-format -msgid "url scheme not specified, assuming http\n" -msgstr "no fue especificado el esquema de url, asumiendo http\n" - -#, c-format -msgid "disk" -msgstr "disco" - -#, c-format -msgid "failed retrieving file '%s' from %s : %s\n" -msgstr "fallo al obtener archivo '%s' desde %s: %s\n" - -#, c-format -msgid "cannot resume download, starting over\n" -msgstr "no se puede resumir la descarga, empezando de nuevo\n" - -#, c-format -msgid "cannot write to file '%s'\n" -msgstr "no se pudo escribir al archivo '%s'\n" - -#, c-format -msgid "error downloading '%s': %s\n" -msgstr "error descargando %s: %s\n" - -#, c-format -msgid "error writing to file '%s': %s\n" -msgstr "no se pudo escribir al archivo '%s': %s\n" - -#, c-format -msgid "could not chdir to %s\n" -msgstr "no se pudo cambiar el directorio a %s\n" - -#, c-format -msgid "running XferCommand: fork failed!\n" -msgstr "ejecutando XferCommand: fallo en el fork\n" - -#, c-format -msgid "URL does not contain a file for download\n" -msgstr "la URL no contiene un archivo para descargar\n" - -#, c-format -msgid "failed to download %s\n" -msgstr "no se pudo descargar %s\n" - -#, c-format msgid "%s-%s: ignoring package upgrade (to be replaced by %s-%s)\n" msgstr "" "%s-%s: ignorando la actualización del paquete (para ser reemplazado por %s-%" @@ -471,22 +433,14 @@ msgid "unresolvable package conflicts detected\n" msgstr "se han detectado paquetes con conflictos no resueltos\n" #, c-format -msgid "malloc failure: could not allocate %zd bytes\n" -msgstr "falla en malloc: no se pudo alocar %zd bytes\n" +msgid "removing '%s' from target list because it conflicts with '%s'\n" +msgstr "quitando '%s' de la lista de objetivos debido a que posee conflictos con '%s'\n" #, c-format msgid "command: %s\n" msgstr "comando: %s\n" #, c-format -msgid "can't get md5 checksum for file %s\n" -msgstr "no se pudo verificar md5 para el paquete %s\n" - -#, c-format -msgid "file %s was corrupted (bad MD5 checksum)\n" -msgstr "el archivo %s estaba corrupto (no coincidió la verificación MD5)\n" - -#, c-format msgid "failed to retrieve some files from %s\n" msgstr "fallo al descargar algunos archivos desde %s\n" @@ -535,6 +489,10 @@ msgid "could not create temp directory\n" msgstr "no se puede crear el directorio temporal\n" #, c-format +msgid "could not copy tempfile to %s (%s)\n" +msgstr "no se pudo copiar el archivo temporal a %s (%s)\n" + +#, c-format msgid "could not change directory to %s (%s)\n" msgstr "no se pudo cambiar el directorio a %s (%s)\n" @@ -567,10 +525,6 @@ msgid "could not remove tmpdir %s\n" msgstr "no se pudo eliminar el directorio temporal %s\n" #, c-format -msgid "failed to make path '%s' : %s\n" -msgstr "fallo al crear la ruta '%s' : %s\n" - -#, c-format msgid "could not open %s: %s\n" msgstr "no se pudo abrir %s: %s\n" @@ -582,10 +536,3 @@ msgstr "no existe la cache %s, creando...\n" msgid "couldn't create package cache, using /tmp instead\n" msgstr "no se pudo crear la cache de paquetes, usando /tmp en su lugar\n" -#, c-format -msgid "md5: %s can't be opened\n" -msgstr "md5: no se puede abrir %s\n" - -#, c-format -msgid "md5: %s can't be read\n" -msgstr "md5: no se puede leer %s\n" diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index a0f9963a..625abe67 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" @@ -57,7 +56,7 @@ int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name) ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - if(_alpm_pkg_find(name, trans->packages)) { + if(_alpm_pkg_find(trans->packages, name)) { RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); } @@ -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(trans->packages, alpm_pkg_get_name(info))) { + _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 = _alpm_pkg_find(trans->packages, miss->causingpkg); + trans->packages = alpm_list_remove(trans->packages, pkg, _alpm_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; @@ -96,37 +149,30 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) return(0); } + if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) { + _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); + _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL); + } + if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); _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 +181,15 @@ 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) { + /* -Rcs == -Rc then -Rs */ + if((trans->flags & PM_TRANS_FLAG_CASCADE) && (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..3dc54d0a 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -22,6 +22,7 @@ #include "config.h" +#include <sys/types.h> /* off_t */ #include <stdlib.h> #include <stdio.h> #include <fcntl.h> @@ -34,7 +35,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 +44,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 +55,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 +70,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 +126,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 +161,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 +203,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 +215,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(replaced, alpm_pkg_get_name(local))) { _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 +282,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 +296,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 +313,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,39 +349,80 @@ 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; + pmpkg_t *p1 = alpm_sync_get_pkg(sp1); + pmpkg_t *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; + off_t size = 0; - p1 = alpm_sync_get_pkg(sp1); - p2 = alpm_sync_get_pkg(sp2); + fname = alpm_pkg_get_filename(newpkg); + ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); + fpath = _alpm_filecache_find(fname); - return(strcmp(alpm_pkg_get_name(p1), alpm_pkg_get_name(p2))); + if(fpath) { + FREE(fpath); + size = 0; + } else if(handle->usedelta) { + off_t dltsize; + off_t 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 %lld for pkg %s\n", + (long long)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) @@ -397,14 +441,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 +457,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 +472,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 +509,130 @@ 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 */ + pmdepend_t *dep1 = _alpm_splitdep(conflict->package1); + pmdepend_t *dep2 = _alpm_splitdep(conflict->package2); + if(alpm_depcmp(sync1->pkg, dep2)) { + rsync = sync2; + sync = sync1; + } else if(alpm_depcmp(sync2->pkg, dep1)) { + 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); + _alpm_dep_free(dep1); + _alpm_dep_free(dep2); + goto cleanup; + } + _alpm_dep_free(dep1); + _alpm_dep_free(dep2); + + /* 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(sync->removes, conflict->package2)) { + 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 +644,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 +666,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) +off_t 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 +682,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 +772,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,26 +802,32 @@ 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; - ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); 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); + /* Total progress - figure out the total download size if required to + * pass to the callback. This function is called once, and it is up to the + * frontend to compute incremental progress. */ + if(handle->totaldlcb) { + off_t total_size = (off_t)0; + /* sum up the download size for each package and store total */ + for(i = trans->packages; i; i = i->next) { + pmsyncpkg_t *sync = i->data; + pmpkg_t *spkg = sync->pkg; + total_size += spkg->download_size; + } + handle->totaldlcb(total_size); } /* group sync records by repository and download */ @@ -997,60 +843,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); } @@ -1059,40 +890,41 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) return(0); } + /* clear out value to let callback know we are done */ + if(handle->totaldlcb) { + handle->totaldlcb(0); + } + if(handle->usedelta) { int ret = 0; /* 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 +935,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 +961,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 +971,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(tr->packages, pkg->name)) { + if(_alpm_trans_addtarget(tr, pkg->name) == -1) { + goto error; } + replaces++; } } } @@ -1175,7 +1003,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 +1016,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 +1031,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 +1042,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 +1074,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 +1082,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..55bd46a8 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" @@ -186,57 +185,65 @@ int _alpm_makepath(const char *path) /* does the same thing as 'mkdir -p' */ int _alpm_makepath_mode(const char *path, mode_t mode) { - char *orig, *str, *ptr; - char full[PATH_MAX] = ""; - mode_t oldmask; - - oldmask = umask(0000); + /* A bit of pointer hell here. Descriptions: + * orig - a copy of path so we can safely butcher it with strsep + * str - the current position in the path string (after the delimiter) + * ptr - the original position of str after calling strsep + * incr - incrementally generated path for use in stat/mkdir call + */ + char *orig, *str, *ptr, *incr; + mode_t oldmask = umask(0000); + int ret = 0; orig = strdup(path); + incr = calloc(strlen(orig) + 1, sizeof(char)); str = orig; while((ptr = strsep(&str, "/"))) { if(strlen(ptr)) { struct stat buf; - - strcat(full, "/"); - strcat(full, ptr); - if(stat(full, &buf)) { - if(mkdir(full, mode)) { - FREE(orig); - umask(oldmask); - _alpm_log(PM_LOG_ERROR, _("failed to make path '%s' : %s\n"), - path, strerror(errno)); - return(1); + /* we have another path component- append the newest component to + * existing string and create one more level of dir structure */ + strcat(incr, "/"); + strcat(incr, ptr); + if(stat(incr, &buf)) { + if(mkdir(incr, mode)) { + ret = 1; + break; } } } } - FREE(orig); + free(orig); + free(incr); umask(oldmask); - return(0); + return(ret); } +#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, (size_t)CPBUFSIZE, (size_t)1, 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 +253,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 +380,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 +398,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 +424,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 +555,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 +660,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 +674,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..ce611f78 100644 --- a/pactest/Makefile.am +++ b/pactest/Makefile.am @@ -8,7 +8,7 @@ check_SCRIPTS = \ pmtest.py \ util.py \ $(wildcard tests/*.py) \ - tests/TESTS + vercmptest.sh noinst_SCRIPTS = $(check_SCRIPTS) diff --git a/pactest/pmtest.py b/pactest/pmtest.py index cd532dcf..e8f6fa8d 100755 --- a/pactest/pmtest.py +++ b/pactest/pmtest.py @@ -83,7 +83,8 @@ class pmtest: "noupgrade": [], "ignorepkg": [], "ignoregroup": [], - "noextract": [] + "noextract": [], + "syncfirst": [] } # Test rules @@ -188,18 +189,22 @@ class pmtest: cmd = [""] if os.geteuid() != 0: - cmd.append("fakeroot") + fakeroot = which("fakeroot") + if not fakeroot: + print "WARNING: fakeroot not found!" + else: + cmd.append("fakeroot") - fakechroot = which("fakechroot") - if not fakechroot: - print "WARNING: fakechroot not found, scriptlet tests WILL fail!!!" - else: - cmd.append("fakechroot") + fakechroot = which("fakechroot") + if not fakechroot: + print "WARNING: fakechroot not found, scriptlet tests WILL fail!!!" + else: + cmd.append("fakechroot") if pacman["gdb"]: - cmd.append("libtool gdb --args") + cmd.append("libtool execute 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 +238,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/remove052.py b/pactest/tests/remove052.py new file mode 100644 index 00000000..df1e0db1 --- /dev/null +++ b/pactest/tests/remove052.py @@ -0,0 +1,21 @@ +self.description = "-Rs test (dependency chain)" + +lp1 = pmpkg("pkg1") +lp1.depends = ["pkg2"] +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +lp2.depends = ["pkg3"] +lp2.reason = 1 +self.addpkg2db("local", lp2) + +lp3 = pmpkg("pkg3") +lp3.reason = 1 +self.addpkg2db("local", lp3) + +self.args = "-Rs %s" % " ".join([p.name for p in lp1, lp3]) + +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/sync301.py b/pactest/tests/sync301.py index e8526b93..96402fc3 100644 --- a/pactest/tests/sync301.py +++ b/pactest/tests/sync301.py @@ -16,10 +16,12 @@ self.addpkg2db("local", lp) lp1 = pmpkg("pkg1", "1.0-1") self.addpkg2db("local", lp1) +self.option["SyncFirst"] = ["pacman"] + self.args = "-Su" self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=pacman") self.addrule("PKG_VERSION=pacman|1.0-2") +self.addrule("PKG_VERSION=pkg1|1.0-1") self.addrule("PKG_EXIST=dep") -self.addrule("PKG_REQUIREDBY=dep|pacman") diff --git a/pactest/tests/sync500.py b/pactest/tests/sync500.py new file mode 100644 index 00000000..ccfffa7c --- /dev/null +++ b/pactest/tests/sync500.py @@ -0,0 +1,15 @@ +self.description = "Install a package from a sync db with NoExtract" + +sp = pmpkg("dummy") +sp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("sync", sp) + +self.option["NoExtract"] = ["usr/man/man1/dummy.1"] + +self.args = "-S %s" % sp.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +self.addrule("FILE_EXIST=bin/dummy") +self.addrule("!FILE_EXIST=usr/man/man1/dummy.1") diff --git a/pactest/tests/sync501.py b/pactest/tests/sync501.py new file mode 100644 index 00000000..eb826e21 --- /dev/null +++ b/pactest/tests/sync501.py @@ -0,0 +1,18 @@ +self.description = "Upgrade a package, with a file in NoUpgrade" + +sp = pmpkg("dummy", "1.0-2") +sp.files = ["etc/dummy.conf"] +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy") +lp.files = ["etc/dummy.conf"] +self.addpkg2db("local", lp) + +self.option["NoUpgrade"] = ["etc/dummy.conf"] + +self.args = "-S %s" % sp.name + +self.addrule("PKG_VERSION=dummy|1.0-2") +self.addrule("!FILE_MODIFIED=etc/dummy.conf") +self.addrule("FILE_PACNEW=etc/dummy.conf") +self.addrule("!FILE_PACSAVE=etc/dummy.conf") 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/upgrade058.py b/pactest/tests/upgrade058.py index 76416802..109289ea 100644 --- a/pactest/tests/upgrade058.py +++ b/pactest/tests/upgrade058.py @@ -14,4 +14,4 @@ self.addpkg(p) self.args = "-U %s" % p.filename() self.addrule("PACMAN_RETCODE=1") -self.addrule("!PKG_VERSION=pkg2|1.1") +self.addrule("!PKG_VERSION=pkg2|1.1-1") 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/pactest/vercmptest.sh b/pactest/vercmptest.sh new file mode 100755 index 00000000..f8d457ee --- /dev/null +++ b/pactest/vercmptest.sh @@ -0,0 +1,100 @@ +#!/bin/sh +# +# vercmptest - a test suite for the vercmp/libalpm program +# +# Copyright (c) 2008 by Dan McGee <dan@archlinux.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/>. + +# default binary if one was not specified as $1 +bin='vercmp' +# holds counts of tests +total=0 +failure=0 + +# args: +# pass ver1 ver2 ret expected +pass() { + echo "test: ver1: $1 ver2: $2 ret: $3 expected: $4" + echo " --> pass" +} + +# args: +# fail ver1 ver2 ret expected +fail() { + echo "test: ver1: $1 ver2: $2 ret: $3 expected: $4" + echo " ==> FAILURE" + failure=$(expr $failure + 1) +} + +# args: +# runtest ver1 ver2 expected +runtest() { + # run the test + ret=$($bin $1 $2) + func='pass' + [ $ret -eq $3 ] || func='fail' + $func $1 $2 $ret $3 + total=$(expr $total + 1) + # and run its mirror case just to be sure + reverse=0 + [ $3 -eq 1 ] && reverse=-1 + [ $3 -eq -1 ] && reverse=1 + ret=$($bin $2 $1) + func='pass' + [ $ret -eq $reverse ] || func='fail' + $func $1 $2 $ret $reverse + total=$(expr $total + 1) +} + +# use first arg as our binary if specified +[ -n "$1" ] && bin="$1" + +# BEGIN TESTS + +# all similar length, no pkgrel +runtest 1.5.0 1.5.0 0 +runtest 1.5.1 1.5.0 1 + +# mixed length +runtest 1.5.1 1.5 1 + +# with pkgrel, simple +runtest 1.5.0-1 1.5.0-1 0 +runtest 1.5.0-1 1.5.0-2 -1 +runtest 1.5.0-1 1.5.1-1 -1 +runtest 1.5.0-2 1.5.1-1 -1 + +# with pkgrel, mixed lengths +runtest 1.5-1 1.5.1-1 -1 +runtest 1.5-2 1.5.1-1 -1 +runtest 1.5-2 1.5.1-2 -1 + +# mixed pkgrel inclusion +runtest 1.5 1.5-1 0 +runtest 1.5-1 1.5 0 +runtest 1.1-1 1.1 0 +runtest 1.0-1 1.1 -1 +runtest 1.1-1 1.0 1 + +#END TESTS + +echo +if [ $failure -eq 0 ]; then + echo "All $total tests successful" + exit 0 +fi + +echo "$failure of $total tests failed" +exit 1 diff --git a/po/POTFILES.in b/po/POTFILES.in index 359a8041..73640f25 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 @@ -10,12 +9,11 @@ src/pacman/pacman.c src/pacman/query.c src/pacman/remove.c src/pacman/sync.c +src/pacman/upgrade.c src/pacman/util.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 @@ -10,9 +10,9 @@ msgid "" msgstr "" "Project-Id-Version: es\n" "Report-Msgid-Bugs-To: pacman-dev@archlinux.org\n" -"POT-Creation-Date: 2008-03-03 20:03-0600\n" -"PO-Revision-Date: 2008-03-03 21:07+0100\n" -"Last-Translator: Fernando Lagos <fernando@zerial.org>\n" +"POT-Creation-Date: 2008-06-12 17:23-0400\n" +"PO-Revision-Date: 2008-06-12 18:57-0400\n" +"Last-Translator: Juan Pablo Gonzalez <jotapesan@gmail.com>\n" "Language-Team: <es@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -22,66 +22,6 @@ msgstr "" "X-Generator: KBabel 1.11.4\n" #, c-format -msgid "failed to release transaction (%s)\n" -msgstr "fallo al lanzar la operación (%s)\n" - -#, c-format -msgid "no targets specified (use -h for help)\n" -msgstr "no se especificaron objetivos (use -h para ayuda)\n" - -#, c-format -msgid "error: %s\n" -msgstr "error: %s\n" - -#, c-format -msgid "" -" if you're sure a package manager is not already\n" -" running, you can remove %s.\n" -msgstr "" -" Si está seguro que no se está ejecutando un\n" -" administrador de paquetes, puede eliminar %s.\n" - -#, c-format -msgid "loading package data...\n" -msgstr "Cargando datos del paquete...\n" - -#, c-format -msgid "error: '%s': %s\n" -msgstr "error: '%s': %s\n" - -#, c-format -msgid "error: failed to prepare transaction (%s)\n" -msgstr "error: fallo al preparar operación (%s)\n" - -#, c-format -msgid ":: %s: requires %s\n" -msgstr ":: %s: necesita %s\n" - -#, c-format -msgid ":: %s: conflicts with %s\n" -msgstr ":: %s: posee conflictos con %s\n" - -#, c-format -msgid "%s exists in both '%s' and '%s'\n" -msgstr "%s existe en '%s' y '%s'\n" - -#, c-format -msgid "%s: %s exists in filesystem\n" -msgstr "%s: %s existe en el sistema de archivos\n" - -#, c-format -msgid "" -"\n" -"errors occurred, no packages were upgraded.\n" -msgstr "" -"\n" -"ocurrieron errores, no fueron actualizados los paquetes\n" - -#, c-format -msgid "error: failed to commit transaction (%s)\n" -msgstr "error: no se pudo iniciar la operación (%s)\n" - -#, c-format msgid "checking dependencies...\n" msgstr "comprobando dependencias...\n" @@ -138,42 +78,32 @@ msgid ":: Retrieving packages from %s...\n" msgstr ":: Descargando paquetes desde %s...\n" #, c-format -msgid "" -":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway? [Y/" -"n] " -msgstr "" -":: %s requiere instalar %s que está en IgnorePkg/IgnoreGroup. ¿Instalar de " -"todas formas? [Y/n] " +msgid ":: %s requires installing %s from IgnorePkg/IgnoreGroup. Install anyway?" +msgstr ":: %s requiere instalar %s que está en IgnorePkg/IgnoreGroup. ¿Instalar de todas formas? " #, c-format -msgid ":: %s is in IgnorePkg/IgnoreGroup. Install anyway? [Y/n] " -msgstr ":: %s está en IgnorePkg/IgnoreGroup. ¿Instalar de todas formas? [Y/n] " +msgid ":: %s is in IgnorePkg/IgnoreGroup. Install anyway?" +msgstr ":: %s está en IgnorePkg/IgnoreGroup. ¿Instalar de todas formas?" #, c-format -msgid ":: %s is designated as a HoldPkg. Remove anyway? [Y/n] " -msgstr ":: %s está indicado como HoldPkg. ¿Quitar de todas formas? [Y/n] " +msgid ":: %s is designated as a HoldPkg. Remove anyway?" +msgstr ":: %s está indicado como HoldPkg. ¿Quitar de todas formas?" #, c-format -msgid ":: Replace %s with %s/%s? [Y/n] " -msgstr ":: ¿Reemplazar %s con %s/%s? [Y/n] " +msgid ":: Replace %s with %s/%s?" +msgstr ":: ¿Reemplazar %s con %s/%s? " #, c-format -msgid "Replacing %s with %s/%s\n" -msgstr "Reemplazando %s con %s/%s\n" +msgid ":: %s conflicts with %s. Remove %s?" +msgstr ":: %s tiene conflictos con %s. ¿Quitar %s?" #, c-format -msgid ":: %s conflicts with %s. Remove %s? [Y/n] " -msgstr ":: %s provoca conflictos con %s. ¿Quitar %s? [Y/n]" +msgid ":: %s-%s: local version is newer. Upgrade anyway?" +msgstr ":: %s-%s: la versión local es más reciente. ¿Actualizar de todas formas?" #, c-format -msgid ":: %s-%s: local version is newer. Upgrade anyway? [Y/n] " -msgstr "" -":: %s-%s: la versión local es más reciente. ¿Actualizar de todas formas? [Y/" -"n] " - -#, c-format -msgid ":: File %s is corrupted. Do you want to delete it? [Y/n] " -msgstr ":: El Archivo %s está corrupto. ¿Desea borrarlo? [Y/n] " +msgid ":: File %s is corrupted. Do you want to delete it?" +msgstr ":: El Archivo %s está corrupto. ¿Desea borrarlo?" #, c-format msgid "installing" @@ -192,6 +122,10 @@ msgid "checking for file conflicts" msgstr "verificando conflictos entre archivos" #, c-format +msgid "malloc failure: could not allocate %zd bytes\n" +msgstr "falla en malloc: no se pudo reservar %zd bytes\n" + +#, c-format msgid "Explicitly installed" msgstr "Explícitamente instalado" @@ -204,10 +138,6 @@ msgid "Unknown" msgstr "Desconocido" #, c-format -msgid "Filename :" -msgstr "Nombre de archivo:" - -#, c-format msgid "Name :" msgstr "Nombre :" @@ -312,8 +242,8 @@ msgid "Backup Files:\n" msgstr "Archivos de respaldo:\n" #, c-format -msgid "error: could not calculate checksums for %s\n" -msgstr "error: no se pudo verificar %s\n" +msgid "could not calculate checksums for %s\n" +msgstr "no se pudo verificar %s\n" #, c-format msgid "MODIFIED\t%s\n" @@ -332,8 +262,8 @@ msgid "(none)\n" msgstr "(nada)\n" #, c-format -msgid "error: no changelog available for '%s'.\n" -msgstr "error: no hay registro de cambios para '%s'.\n" +msgid "no changelog available for '%s'.\n" +msgstr "no hay registro de cambios disponible para '%s'.\n" #, c-format msgid "options" @@ -364,29 +294,17 @@ msgstr "" "digite '%s --help' con otra opción para ayuda más específica\n" #, c-format -msgid " --asdeps install packages as non-explicitly installed\n" -msgstr " --asdeps instala paquetes como dependencia\n" +msgid " -c, --cascade remove packages and all packages that depend on them\n" +msgstr "" +" -c, --cascade quita paquetes, junto a todos los que dependan de " +"estos\n" #, c-format msgid " -d, --nodeps skip dependency checks\n" msgstr " -d, --nodeps salta la verificación de dependencias \n" #, c-format -msgid " -f, --force force install, overwrite conflicting files\n" -msgstr "" -" -f, --force fuerza la instalación, sobreescribiendo los archivos " -"en conflicto\n" - -#, c-format -msgid "" -" -c, --cascade remove packages and all packages that depend on them\n" -msgstr "" -" -c, --cascade quita paquetes, junto a todos los que dependan de " -"estos\n" - -#, c-format -msgid "" -" -k, --dbonly only remove database entry, do not remove files\n" +msgid " -k, --dbonly only remove database entry, do not remove files\n" msgstr "" " -k, --dbonly sólo quita la referencia en la base de datos. No " "elimina archivos\n" @@ -398,9 +316,28 @@ msgstr " -n, --nosave quita también los archivos de configuración\n" #, c-format msgid "" " -s, --recursive remove dependencies also (that won't break packages)\n" +" (-ss includes explicitly installed dependencies too)\n" +msgstr "" +" -s, --recursive quita también las dependencias (que no quiebren a otros paquetes)\n" +" (-ss incluye también las dependencias explicitamente instaladas)\n" + +#, c-format +msgid " -u, --unneeded remove unneeded packages (that won't break packages)\n" +msgstr " -u, --unneeded quita los paquetes no necesitados (que no quiebren a otros paquetes)\n" + +#, c-format +msgid " --asdeps install packages as non-explicitly installed\n" +msgstr " --asdeps instala paquetes como dependencia\n" + +#, c-format +msgid " --asexplicit install packages as explicitly installed\n" +msgstr " --asexplicit instala paquetes como explicitamente instalados\n" + +#, c-format +msgid " -f, --force force install, overwrite conflicting files\n" msgstr "" -" -s, --recursive quita también las dependencias (que no quiebren a " -"otros paquetes)\n" +" -f, --force fuerza la instalación, sobreescribiendo los archivos " +"en conflicto\n" #, c-format msgid " -c, --changelog view the changelog of a package\n" @@ -414,17 +351,14 @@ msgstr "" #, c-format msgid " -e, --explicit list all packages explicitly installed\n" -msgstr "" -" -e, --explicit lista todos los paquetes instalados explicitamente\n" +msgstr " -e, --explicit lista todos los paquetes instalados explicitamente\n" #, c-format msgid " -g, --groups view all members of a package group\n" -msgstr "" -" -g, --groups muestra todos los elementos del grupo de paquetes \n" +msgstr " -g, --groups muestra todos los elementos del grupo de paquetes \n" #, c-format -msgid "" -" -i, --info view package information (-ii for backup files)\n" +msgid " -i, --info view package information (-ii for backup files)\n" msgstr "" " -i, --info ver la información del paquete (-ii para archivos de " "respaldo)\n" @@ -436,8 +370,7 @@ msgstr "" "consultados\n" #, c-format -msgid "" -" -m, --foreign list installed packages not found in sync db(s)\n" +msgid " -m, --foreign list installed packages not found in sync db(s)\n" msgstr "" " -m, --foreign lista paquetes instalados no encontrados en las " "listas de paquetes\n" @@ -489,10 +422,6 @@ msgstr "" "(-cc para todos los paquetes)\n" #, c-format -msgid " -e, --dependsonly install dependencies only\n" -msgstr " -e, --dependsonly instala sólo dependencias\n" - -#, c-format msgid " -i, --info view package information\n" msgstr " -i, --info ver la información del paquete\n" @@ -509,16 +438,12 @@ msgstr "" "archivos indicados y sus dependencias\n" #, c-format -msgid "" -" -s, --search <regex> search remote repositories for matching strings\n" -msgstr "" -" -s, --search <busca> busca en los repositorios remotos por coincidencias " -"de la cadena especificada.\n" +msgid " -s, --search <regex> search remote repositories for matching strings\n" +msgstr " -s, --search <busca> busca en los repositorios remotos por coincidencias de la cadena especificada.\n" #, c-format msgid " -u, --sysupgrade upgrade all packages that are out of date\n" -msgstr "" -" -u, --sysupgrade actualiza todos los paquetes que no están al día\n" +msgstr " -u, --sysupgrade actualiza todos los paquetes que no están al día\n" #, c-format msgid "" @@ -529,25 +454,23 @@ msgstr "" "nada\n" #, c-format -msgid "" -" -y, --refresh download fresh package databases from the server\n" +msgid " -y, --refresh download fresh package databases from the server\n" msgstr "" " -y, --refresh descarga bases de datos actualizadas desde el " "servidor\n" #, c-format -msgid "" -" --needed only upgrade outdated or not yet installed packages\n" +msgid " --needed only upgrade outdated or not yet installed packages\n" msgstr "" " --needed solo actualiza paquetes antiguos o los que no\n" -" están instalados\n" +" están instalados\n" #, c-format msgid "" " --ignore <pkg> ignore a package upgrade (can be used more than " "once)\n" msgstr "" -" --ignore <pkg> ignora una actualización de paquete (puede ser usado " +" --ignore <paq> ignora una actualización de paquete (puede ser usado " "más de una vez)\n" #, c-format @@ -555,8 +478,8 @@ msgid "" " --ignoregroup <grp>\n" " ignore a group upgrade (can be used more than once)\n" msgstr "" -" --ignoregroup <pkg>\n" -" ignora una actualización de grupo (puede ser usado más " +" --ignoregroup <grp>\n" +" ignora una actualización de grupo (puede ser usado más " "de una vez)\n" #, c-format @@ -578,17 +501,14 @@ msgid " --noconfirm do not ask for any confirmation\n" msgstr " --noconfirm no solicita confirmación alguna\n" #, c-format -msgid "" -" --noprogressbar do not show a progress bar when downloading files\n" +msgid " --noprogressbar do not show a progress bar when downloading files\n" msgstr "" " --noprogressbar no muestra la barra de progreso cuando descarga " "archivos\n" #, c-format -msgid "" -" --noscriptlet do not execute the install scriptlet if one exists\n" -msgstr "" -" --noscriptlet no ejecuta el script de instalación si existe alguno\n" +msgid " --noscriptlet do not execute the install scriptlet if one exists\n" +msgstr " --noscriptlet no ejecuta el script de instalación si existe alguno\n" #, c-format msgid " -v, --verbose be verbose\n" @@ -616,8 +536,19 @@ msgid "" " the terms of the GNU General Public License\n" msgstr "" " Este programa puede ser libremente distribuido bajo\n" -" los términos de la licencia GNU General Public " -"License\n" +" los términos de la licencia GNU General Public License\n" + +#, c-format +msgid "segmentation fault\n" +msgstr "Violación de segmento\n" + +#, c-format +msgid "" +"Internal pacman error: Segmentation fault.\n" +"Please submit a full bug report with --debug if appropriate.\n" +msgstr "" +"error interno de pacman error: Violación de segmento.\n" +"Por favor envíe un reporte de errores con la opción --debug si es oportuno.\n" #, c-format msgid "problem setting rootdir '%s' (%s)\n" @@ -665,12 +596,15 @@ msgstr "" #, c-format msgid "config file %s, line %d: directive '%s' not recognized.\n" -msgstr "" -"archivo de configuración %s, linea %d: directiva '%s' no es reconocida.\n" +msgstr "archivo de configuración %s, linea %d: directiva '%s' no es reconocida.\n" + +#, c-format +msgid "invalid value for 'CleanMethod' : '%s'\n" +msgstr "valor invalido para 'CleanMethod' : '%s'\n" #, c-format msgid "failed to initialize alpm library (%s)\n" -msgstr "fallo al iniciar la librería alpm (%s)\n" +msgstr "falló al iniciar la librería alpm (%s)\n" #, c-format msgid "you cannot perform this operation unless you are root.\n" @@ -685,36 +619,36 @@ msgid "no operation specified (use -h for help)\n" msgstr "no se especificó una operación (utilice -h para ayuda)\n" #, c-format -msgid "error: no file was specified for --owns\n" -msgstr "error: no se indicó un archivo para --owns\n" +msgid "no file was specified for --owns\n" +msgstr "no se indicó un archivo para --owns\n" #, c-format -msgid "error: failed to read file '%s': %s\n" -msgstr "error: no se pudo leer el archivo '%s': %s\n" +msgid "failed to read file '%s': %s\n" +msgstr "no se pudo leer el archivo '%s': %s\n" #, c-format -msgid "error: cannot determine ownership of a directory\n" -msgstr "error: no se pudo determinar el propietario de un directorio\n" +msgid "cannot determine ownership of a directory\n" +msgstr "no se pudo determinar al propietario de un directorio\n" #, c-format -msgid "error: cannot determine real path for '%s': %s\n" -msgstr "error: no se pudo determinar la ruta verdadera para '%s': %s\n" +msgid "cannot determine real path for '%s': %s\n" +msgstr "no se pudo determinar la ruta verdadera para '%s': %s\n" #, c-format msgid "%s is owned by %s %s\n" msgstr "%s es propiedad de %s %s\n" #, c-format -msgid "error: No package owns %s\n" -msgstr "error: Ningún paquete posee %s\n" +msgid "No package owns %s\n" +msgstr "Ningún paquete posee %s\n" #, c-format -msgid "error: group \"%s\" was not found\n" -msgstr "error: el grupo \"%s\" no fue encontrado\n" +msgid "group \"%s\" was not found\n" +msgstr "el grupo \"%s\" no fue encontrado\n" #, c-format msgid "Checking for package upgrades... \n" -msgstr "Verificando existencia de actualizaciones de paquetes...\n" +msgstr "Verificando si hay actualizaciones de paquetes...\n" #, c-format msgid "no upgrades found.\n" @@ -725,56 +659,72 @@ msgid "no usable package repositories configured.\n" msgstr "no se encontraron repositorios útiles configurados.\n" #, c-format -msgid "error: package \"%s\" not found\n" -msgstr "error: el paquete \"%s\" no fue encontrado\n" +msgid "no targets specified (use -h for help)\n" +msgstr "no se especificaron objetivos (use -h para ayuda)\n" + +#, c-format +msgid "package \"%s\" not found\n" +msgstr "el paquete \"%s\" no fue encontrado\n" #, c-format msgid ":: group %s:\n" msgstr ":: grupo %s:\n" #, c-format -msgid " Remove whole content? [Y/n] " -msgstr " ¿Quitar todo el contenido? [Y/n] " +msgid " Remove whole content?" +msgstr " ¿Quitar todo el contenido?" #, c-format -msgid ":: Remove %s from group %s? [Y/n] " -msgstr ":: ¿Quitar %s del grupo %s? [Y/n] " +msgid ":: Remove %s from group %s?" +msgstr ":: ¿Quitar %s del grupo %s?" #, c-format -msgid "error: failed to init transaction (%s)\n" -msgstr "error: no se pudo iniciar la operación (%s)\n" +msgid "loading package data...\n" +msgstr "cargando datos del paquete...\n" + +#, c-format +msgid "failed to prepare transaction (%s)\n" +msgstr "fallo al preparar la transacción (%s)\n" + +#, c-format +msgid ":: %s: requires %s\n" +msgstr ":: %s: necesita %s\n" #, c-format msgid "Targets:" -msgstr "Se procesará:" +msgstr "Objetivos:" #, c-format msgid "" "\n" -"Do you want to remove these packages? [Y/n] " +"Do you want to remove these packages?" msgstr "" "\n" -"¿Quiere eliminar estos paquetes? [Y/n] " +"¿Quiere eliminar estos paquetes?" #, c-format -msgid "error: could not access database directory\n" -msgstr "error: no se pudo acceder al directorio de la cache\n" +msgid "failed to commit transaction (%s)\n" +msgstr "no se pudo iniciar la operación (%s)\n" #, c-format -msgid "Do you want to remove %s? [Y/n] " -msgstr "¿Quiere eliminar %s? [Y/n] " +msgid "could not access database directory\n" +msgstr "no se pudo acceder al directorio de la base de datos\n" #, c-format -msgid "error: could not remove repository directory\n" -msgstr "error: no se pudo eliminar el directorio del repositorio\n" +msgid "Do you want to remove %s?" +msgstr "¿Quiere eliminar %s?" + +#, c-format +msgid "could not remove repository directory\n" +msgstr "no se pudo eliminar el directorio del repositorio\n" #, c-format msgid "Database directory: %s\n" msgstr "Directorio de la base de datos: %s\n" #, c-format -msgid "Do you want to remove unused repositories? [Y/n] " -msgstr "¿Quiere eliminar estos repositorios no utilizados? [Y/n] " +msgid "Do you want to remove unused repositories?" +msgstr "¿Quiere eliminar estos repositorios no utilizados?" #, c-format msgid "Database directory cleaned up\n" @@ -785,146 +735,162 @@ msgid "Cache directory: %s\n" msgstr "Directorio de cache: %s\n" #, c-format -msgid "Do you want to remove uninstalled packages from cache? [Y/n] " -msgstr "Desea borrar todos los paquetes desinstalados de la cache? [Y/n] " +msgid "Do you want to remove uninstalled packages from cache?" +msgstr "Desea borrar todos los paquetes desinstalados de la cache?" + +#, c-format +msgid "Do you want to remove outdated packages from cache?" +msgstr "Desea borrar todos los paquetes desactualizados de la cache? " #, c-format msgid "removing old packages from cache... " msgstr "quitando paquetes antiguos de la cache..." #, c-format -msgid "error: could not access cache directory\n" -msgstr "error: no se pudo acceder al directorio de la cache\n" +msgid "could not access cache directory\n" +msgstr "no se pudo acceder al directorio de la cache\n" #, c-format msgid "done.\n" msgstr "hecho.\n" #, c-format -msgid "Do you want to remove ALL packages from cache? [Y/n] " -msgstr "Desea quitar TODOS los paquetes de la cache? [Y/n] " +msgid "Do you want to remove ALL packages from cache?" +msgstr "Desea quitar TODOS los paquetes de la cache?" #, c-format msgid "removing all packages from cache... " msgstr "quitando todos los paquetes de la cache... " #, c-format -msgid "error: could not remove cache directory\n" -msgstr "error: no se pudo eliminar el directorio de la cache\n" - -#, c-format -msgid "error: could not create new cache directory\n" -msgstr "error: no se pudo crear el nuevo directorio de la cache\n" +msgid "could not remove cache directory\n" +msgstr "no se pudo eliminar el directorio de la cache\n" #, c-format -msgid "error: failed to release transaction (%s)\n" -msgstr "fallo al liberar la operación (%s)\n" +msgid "could not create new cache directory\n" +msgstr "no se pudo crear el nuevo directorio de la cache\n" #, c-format -msgid "error: failed to synchronize %s: %s\n" -msgstr "error: fallo al sincronizar %s: %s\n" - -#, c-format -msgid "error: failed to update %s (%s)\n" -msgstr "fallo al actualizar %s (%s)\n" +msgid "failed to update %s (%s)\n" +msgstr "falló al actualizar %s (%s)\n" #, c-format msgid " %s is up to date\n" msgstr " %s está actualizado\n" #, c-format -msgid "error: repository '%s' does not exist\n" -msgstr "error: el repositorio '%s' no existe\n" +msgid "failed to synchronize any databases\n" +msgstr "falló al sincronizar cualquier base de datos\n" #, c-format -msgid "error: package '%s' was not found in repository '%s'\n" -msgstr "error: el paquete '%s' no fue encontrado en el repositorio '%s'\n" +msgid "repository '%s' does not exist\n" +msgstr "el repositorio '%s' no existe\n" #, c-format -msgid "error: package '%s' was not found\n" -msgstr "error: El paquete '%s' no fue encontrado\n" +msgid "package '%s' was not found in repository '%s'\n" +msgstr "el paquete '%s' no fue encontrado en el repositorio '%s'\n" #, c-format -msgid "error: repository \"%s\" was not found.\n" -msgstr "error: el repositorio \"%s\" no fue encontrado.\n" +msgid "package '%s' was not found\n" +msgstr "El paquete '%s' no fue encontrado\n" #, c-format -msgid ":: Synchronizing package databases...\n" -msgstr ":: Sincronizando las bases de datos de paquetes...\n" - -#, c-format -msgid "error: failed to synchronize any databases\n" -msgstr "error: falló al sincronizar cualquier base de datos\n" +msgid "repository \"%s\" was not found.\n" +msgstr "el repositorio \"%s\" no fue encontrado.\n" #, c-format msgid ":: Starting full system upgrade...\n" msgstr ":: iniciando actualización completa del sistema...\n" #, c-format -msgid ":: pacman has detected a newer version of itself.\n" -msgstr ":: pacman ha detectado una nueva version de si mismo.\n" - -#, c-format -msgid "" -":: Do you want to cancel the current operation\n" -":: and install the new pacman version now? [Y/n] " -msgstr "" -":: Desea cancelar la operacion actual\n" -":: e instalar la nueva versin de pacman ahora? [S/n] " - -#, c-format -msgid "error: pacman: %s\n" -msgstr "error: pacman: %s\n" - -#, c-format msgid ":: group %s (including ignored packages):\n" msgstr ":: grupo %s (incluyendo los paquetes ignorados):\n" #, c-format -msgid ":: Install whole content? [Y/n] " -msgstr ":: ¿Instalar el todo el contenido? [Y/n] " +msgid ":: Install whole content?" +msgstr ":: ¿Instalar el todo el contenido?" #, c-format -msgid ":: Install %s from group %s? [Y/n] " -msgstr ":: ¿Instalar %s del grupo %s? [Y/n] " +msgid ":: Install %s from group %s?" +msgstr ":: ¿Instalar %s del grupo %s?" #, c-format msgid "Warning: %s provides %s\n" msgstr "Advertencia: %s: provee %s\n" #, c-format -msgid "error: several packages provide %s, please specify one :\n" -msgstr "error: varios paquetes proveen %s, por favor especifique uno :\n" +msgid "several packages provide %s, please specify one :\n" +msgstr "varios paquetes proveen %s, por favor especifique uno :\n" #, c-format -msgid "error: '%s': not found in sync db\n" -msgstr "error: '%s': no encontrado en la lista de paquetes\n" +msgid "'%s': not found in sync db\n" +msgstr "'%s': no encontrado en la lista de paquetes\n" + +#, c-format +msgid ":: %s: conflicts with %s\n" +msgstr ":: %s: posee conflictos con %s\n" #, c-format msgid " local database is up to date\n" msgstr "la base de datos local está actualizada\n" #, c-format -msgid "Beginning download...\n" -msgstr "Empezando la descarga...\n" +msgid "Proceed with download?" +msgstr "¿Continuar con la descarga?" + +#, c-format +msgid "Proceed with installation?" +msgstr "¿Continuar con la instalación?" #, c-format -msgid "Proceed with download? [Y/n] " -msgstr "¿Continuar con la descarga? [Y/n] " +msgid "%s exists in both '%s' and '%s'\n" +msgstr "%s existe tanto en '%s' como en '%s'\n" #, c-format -msgid "Beginning upgrade process...\n" -msgstr "Empezando proceso de actualización...\n" +msgid "%s: %s exists in filesystem\n" +msgstr "%s: %s existe en el sistema de archivos\n" #, c-format -msgid "Proceed with installation? [Y/n] " -msgstr "¿Continuar con la instalación? [Y/n] " +msgid "%s is invalid or corrupted\n" +msgstr "%s es invalido o está corrupto\n" #, c-format msgid "Errors occurred, no packages were upgraded.\n" msgstr "Ocurrieron errores, no se actualizaron paquetes\n" #, c-format +msgid ":: Synchronizing package databases...\n" +msgstr ":: Sincronizando las bases de datos de paquetes...\n" + +#, c-format +msgid ":: The following packages should be upgraded first :\n" +msgstr ":: Los siguientes paquetes debieran ser actualizados primero :\n" + +#, c-format +msgid "" +":: Do you want to cancel the current operation\n" +":: and upgrade these packages now?" +msgstr "" +":: Desea cancelar la operación actual\n" +":: e instalar la nueva versión de pacman ahora?" + +#, c-format +msgid "failed to init transaction (%s)\n" +msgstr "no se pudo iniciar la transacción (%s)\n" + +#, c-format +msgid "" +" if you're sure a package manager is not already\n" +" running, you can remove %s\n" +msgstr "" +" si está seguro que no se está ejecutando un\n" +" administrador de paquetes, puede eliminar %s.\n" + +#, c-format +msgid "failed to release transaction (%s)\n" +msgstr "falló al lanzar la transacción (%s)\n" + +#, c-format msgid "None\n" msgstr "Nada\n" @@ -945,6 +911,14 @@ msgid "Total Installed Size: %.2f MB\n" msgstr "Tamaño total instalado: %.2f MB\n" #, c-format +msgid "[Y/n]" +msgstr "[Y/n]" + +#, c-format +msgid "[y/N]" +msgstr "[y/N]" + +#, c-format msgid "Y" msgstr "Y" @@ -953,6 +927,14 @@ msgid "YES" msgstr "YES" #, c-format +msgid "N" +msgstr "N" + +#, c-format +msgid "NO" +msgstr "NO" + +#, c-format msgid "error: %s" msgstr "error: %s" @@ -976,75 +958,13 @@ msgstr "precaución: " msgid "function: " msgstr "función: " -msgid "Usage: %s <root> <destfile> [package_directory]" -msgstr "Uso: %s <root> <destfile> [directorio_del_paquete]" - -msgid "" -"NOTE: this script is DEPRECATED. It will be removed in the next major" -"\\nrelease of pacman, so please use repo-add and repo-remove instead.\\n\\n" -msgstr "" -"NOTA: Este script esta OBSOLETO. Sera removido en la proxima versionde " -"pacman, por favor use repo-add y repo-remove.\\n\\n" - -msgid "" -"gensync will generate a sync database by reading all PKGBUILD files\\nfrom " -"<root>. gensync builds the database in a temporary directory\\nand then " -"compresses it to <destfile>.\\n\\n" -msgstr "" -"gensync creará una base de datos leyendo todos los PKGBUILDs\\n de <root>. " -"gensync crea la base de datos en un directorio temporal\\ny entonces la " -"comprime a <destfile>.\\n\\n" - -msgid "" -"gensync will calculate md5sums of packages in the same directory as" -"\\n<destfile>, unless an alternate [package_directory] is specified.\\n\\n" -msgstr "" -"gensync calculará el md5 de los paquetes en el mismo directorio que " -"\\n<destfile>, a menos que un directorio alternativo [package_directory] sea " -"especificado \\n\\n" - -msgid "" -"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" -msgstr "" -"nota: el nombre <destfile> es importante. Debe ser de la forma\\n " -"{treename}.db.tar.gz donde {treename} es el nombre del repositorio\\n " -"personalizado que configuraste en /etc/pacman.conf. La\\n base generada " -"debe estar en el mismo directorio que tus paquetes(también configurado en /" -"etc/pacman.conf)\\n\\n" - -msgid "Example: gensync /var/abs/local /home/mypkgs/custom.db.tar.gz" -msgstr "Ejemplo: gensync /var/abs/local /home/mypkgs/custom.db.tar.gz" - +#, c-format msgid "" -"Copyright (C) 2002-2007 Judd Vinet <jvinet@zeroflux.org>.\\n\\nThis is free " -"software; see the source for copying conditions.\\nThere is NO WARRANTY, to " -"the extent permitted by law.\\n" +"\n" +"errors occurred, no packages were upgraded.\n" msgstr "" -"Copyright (C) 2002-2007 Judd Vinet <jvinet@zeroflux.org>. \\n\\nEsto es " -"Software libre; Ver el código fuente para condiciones de copia.\\nNO HAY " -"GARANTÍA, hasta los límites permitidos por la ley.\\n" - -msgid "%s not found. Can not continue." -msgstr "%s no se encuentra. No se puede continuar." - -msgid "invalid root dir: %s" -msgstr "directorio raíz invalido: %s" - -msgid "gensync: building database entries, generating md5sums..." -msgstr "gensync: contruyendo base de datos, generando hash md5..." - -msgid "failed to parse %s" -msgstr "fallo al analizar %s" - -msgid "could not find %s-%s-%s-%s%s - skipping" -msgstr "no se pudo encontrar %s-%s-%s-%s %s - saltando" - -msgid "creating repo DB..." -msgstr "creando la BD del repositorio..." +"\n" +"ocurrieron errores, no fueron actualizados los paquetes\n" msgid "WARNING:" msgstr "PRECAUCIÓN:" @@ -1055,21 +975,6 @@ msgstr "ERROR:" msgid "Cleaning up..." msgstr "Limpiando..." -msgid "" -"Options beginning with 'no' will be deprecated in the next version of " -"makepkg!" -msgstr "" -"Las opciones que comiencen con 'no' serán abandonadas en la próxima versión " -"de makepkg!" - -msgid "Please replace 'no' with '!': %s -> %s." -msgstr "Por favor reemplace 'no' con '!': %s -> %s." - -msgid "Option 'keepdocs' may not work as intended. Please replace with 'docs'." -msgstr "" -"La opción 'keepdocs' puede no funcionar como se planea. Por favor, " -"reemplazala con 'docs'." - msgid "There is no agent set up to handle %s URLs. Check %s." msgstr "No hay nada configurado para las URLs %s. Comprueba %s." @@ -1088,24 +993,15 @@ msgstr "Instalado dependencias faltantes... " msgid "Pacman failed to install missing dependencies." msgstr "Pacman falló al instalar las dependencias faltantes." -msgid "Building missing dependencies..." -msgstr "Construyendo dependencias faltantes... " - -msgid "Source root cannot be found - please make sure it is specified in %s." -msgstr "La raíz no se pudo encontrar - asegurate que está especificada en %s" - -msgid "Could not find '%s' under %s" -msgstr "No se pudo encontrar '%s' en '%s'" - -msgid "Failed to build '%s'" -msgstr "Fallo al construir '%s'" - msgid "Failed to install all missing dependencies." msgstr "Fallo al instalar todas las dependencias faltantes." msgid "Missing Dependencies:" msgstr "Dependencias Faltantes " +msgid "Failed to remove installed dependencies." +msgstr "Falló al quitar las dependencias instaladas." + msgid "Retrieving Sources..." msgstr "Obteniendo Fuentes..." @@ -1119,7 +1015,7 @@ msgid "Using cached copy of %s" msgstr "usando copia cacheada de %s" msgid "%s was not found in the build directory and is not a URL." -msgstr "%s no fue encontrado en el directorio build y no es una URL." +msgstr "%s no fue encontrado en el directorio de compilación y no es una URL." msgid "Downloading %s..." msgstr "Descargando %s... " @@ -1152,13 +1048,13 @@ msgid "Passed" msgstr "Pasado" msgid "FAILED" -msgstr "FALLO" +msgstr "FALLÓ" msgid "One or more files did not pass the validity check!" -msgstr "¡Uno o más archivos no pasaron el test de integridad!" +msgstr "¡Uno o más archivos no pasaron la verificación de integridad!" msgid "Integrity checks (%s) are missing or incomplete." -msgstr "Faltan los test de integridad (%s) o están incompletos" +msgstr "Faltan las pruebas de integridad (%s) o están incompletas" msgid "Extracting Sources..." msgstr "Descomprimiendo fuentes..." @@ -1185,7 +1081,7 @@ msgid "Compressing man pages..." msgstr "Comprimiendo las paginas man..." msgid "Stripping debugging symbols from binaries and libraries..." -msgstr "Quitando símbolos de debug de los bianrios y librerías..." +msgstr "Quitando símbolos de depuración de los binarios y librerías..." msgid "Removing libtool .la files..." msgstr "eliminando archivos .la..." @@ -1286,9 +1182,6 @@ msgstr "Opciones:" msgid " -A, --ignorearch Ignore incomplete arch field in %s" msgstr " -A, --ignorearch Ignorar campo arch incompleto en %s" -msgid " -b, --builddeps Build missing dependencies from source" -msgstr " -b, --builddeps Compilar las dependencias desde las fuentes" - msgid " -c, --clean Clean up work files after build" msgstr " -c, --clean Limpiar archivos tras la compilación" @@ -1299,13 +1192,13 @@ msgid " -d, --nodeps Skip all dependency checks" msgstr " -d, --nodeps salta la verificación de dependencias" msgid " -e, --noextract Do not extract source files (use existing src/ dir)" -msgstr " -e, --noextract No extraer las fuentes (usar el directorio src/)" +msgstr " -e, --noextract No extraer los fuentes (usar el directorio src/)" msgid " -f, --force Overwrite existing package" msgstr " -f, --force Sobreescribe el paquete existente" msgid " -g, --geninteg Generate integrity checks for source files" -msgstr " -g, --geninteg Generar test de integridad para las fuentes" +msgstr " -g, --geninteg Generar verificaciones de integridad para los fuentes" msgid " -h, --help This help" msgstr " -h, --help Esta ayuda" @@ -1325,8 +1218,7 @@ msgstr " -o, --nobuild Sólo descargar y extraer" msgid " -p <buildscript> Use an alternate build script (instead of '%s')" msgstr " -p <buildscript> Usar un script alternativo (en vez de '%s')" -msgid "" -" -r, --rmdeps Remove installed dependencies after a successful build" +msgid " -r, --rmdeps Remove installed dependencies after a successful build" msgstr "" " -r, --rmdeps Elimina las dependencias instaladas tras una creación " "exitosa." @@ -1338,7 +1230,7 @@ msgid " -s, --syncdeps Install missing dependencies with pacman" msgstr " -s, --syncdeps Instala las dependencias faltantes con pacman" msgid " --asroot Allow makepkg to run as root user" -msgstr " --asroot Permitir a makepkg ser ejecutado como root" +msgstr " --asroot Permitir a makepkg ser ejecutado como el usuario root" msgid "" " --holdver Prevent automatic version bumping for development " @@ -1348,8 +1240,7 @@ msgstr "" "PKGBUILD de desarrollo" msgid " --source Do not build package; generate a source-only tarball" -msgstr "" -" --source No construir el paquete, crear un tarball com sólo fuentes" +msgstr " --source No construir el paquete, crear un tarball con sólo los fuentes" msgid "These options can be passed to pacman:" msgstr "Estas opciones pueden ser pasadas a pacman:" @@ -1358,11 +1249,10 @@ msgid "" " --noconfirm Do not ask for confirmation when resolving " "dependencies" msgstr "" -" --noconfirm no solicita confirmación alguna cuado se encuentra " -"resolviendo dependencias" +" --noconfirm no solicita confirmación alguna cuando se encuentra resolviendo " +"dependencias" -msgid "" -" --noprogressbar Do not show a progress bar when downloading files" +msgid " --noprogressbar Do not show a progress bar when downloading files" msgstr "" " --noprogressbar No muestra la barra de progreso cuando descarga " "archivos" @@ -1370,6 +1260,15 @@ msgstr "" msgid "If -p is not specified, makepkg will look for '%s'" msgstr "Si no se especifica -p, makepkg buscará '%s'" +msgid "" +"Copyright (C) 2002-2007 Judd Vinet <jvinet@zeroflux.org>.\\n\\nThis is free " +"software; see the source for copying conditions.\\nThere is NO WARRANTY, to " +"the extent permitted by law.\\n" +msgstr "" +"Copyright (C) 2002-2007 Judd Vinet <jvinet@zeroflux.org>. \\n\\nEsto es " +"Software libre; Ver el código fuente para condiciones de copia.\\nNO HAY " +"GARANTÍA, en el grado permitido por la ley.\\n" + msgid "%s not found." msgstr "el paquete %s no fue encontrado." @@ -1400,10 +1299,10 @@ msgid "Source destination must be defined in makepkg.conf." msgstr "La destinación de las fuentes debe ser definido en makepkg.conf." msgid "In addition, please run makepkg -C outside of your cache directory." -msgstr "Adicionalmente, por favor, ejecuta makepkg -C fuera de tu cache." +msgstr "Adicionalmente, por favor, ejecute makepkg -C fuera de su directorio de cache." msgid "BUILDSCRIPT is undefined! Ensure you have updated %s." -msgstr "¡BUILDSCRIPT está sin definir! Asegurate de que hayas actualizado %s." +msgstr "¡BUILDSCRIPT está sin definir! Asegúrese de que haya actualizado %s." msgid "Running makepkg as root is a BAD idea and can cause" msgstr "Ejecutar makepkg como root es una MALA idea y puede causar" @@ -1424,11 +1323,10 @@ msgid "Fakeroot must be installed if using the 'fakeroot' option" msgstr "Fakeroot debe ser instalado si se usa la opción 'fakeroot'" msgid "in the BUILDENV array in %s." -msgstr "en la línea BUILDENV en %s." +msgstr "en el arreglo BUILDENV en %s." msgid "Running makepkg as an unprivileged user will result in non-root" -msgstr "" -"Ejecutar makepkg como un usuario sin privilegios resultará en unos paquetes" +msgstr "Ejecutar makepkg como un usuario sin privilegios resultará en unos paquetes" msgid "ownership of the packaged files. Try using the fakeroot environment by" msgstr "no pertenecientes a root. Prueba usando fakeroot " @@ -1471,6 +1369,9 @@ msgstr "como por ejemplo arch=('%s')." msgid "Install scriptlet (%s) does not exist." msgstr "El script de instalación (%s) no existe." +msgid "options array contains unknown option '%s'" +msgstr "el arreglo de opciones contiene la opción desconocida '%s'" + msgid "A package has already been built, installing existing package..." msgstr "El paquete ya ha sido compilado, instalando el paquete preexistente..." @@ -1490,29 +1391,28 @@ msgid "Running makepkg as root..." msgstr "Ejecutando makepkg como root..." msgid "Source package created: %s" -msgstr "Pauqete fuente creado: %s" +msgstr "Paquete fuente creado: %s" msgid "Skipping dependency checks." msgstr "Saltando la verificación de dependencias... " msgid "Checking Runtime Dependencies..." -msgstr "Comprobando Dependencias en tiempo de ejecución... " +msgstr "Comprobando Dependencias en tiempo de Ejecución... " msgid "Checking Buildtime Dependencies..." -msgstr "comprobando dependencias en tiempo de compilación... " +msgstr "Comprobando Dependencias en tiempo de Compilación... " msgid "Could not resolve all dependencies." msgstr "No se pudieron resolver todas las dependencias... " msgid "pacman was not found in PATH; skipping dependency checks." -msgstr "" -"no se encontró pacman en el PATH; saltando la comprobación de dependencias." +msgstr "no se encontró pacman en el PATH; saltando la comprobación de dependencias." msgid "Skipping source retrieval -- using existing src/ tree" -msgstr "Saltando obtención de fuentes -- usando src/tree existente" +msgstr "Saltando obtención de fuentes -- usando el arbol src/ existente" msgid "Skipping source integrity checks -- using existing src/ tree" -msgstr "saltando test de integridad -- usando src/tree existente" +msgstr "saltando pruebas de integridad -- usando el arbol src/ existente" msgid "Skipping source extraction -- using existing src/ tree" msgstr "Saltando extracción de las fuentes -- usando src/tree existente" @@ -1543,7 +1443,7 @@ msgid "" "pacman when reading/writing to its filesystem-based database.\\n\\n" msgstr "" "pacman-optimize es un pequeño hack que debería aumentar el rendimiento\\nde " -"pacman caudno lea/escriba en su baso de datos\\n\\n" +"pacman cuando lea/escriba en su baso de datos\\n\\n" msgid "" "Because pacman uses many small files to keep track of packages,\\nthere is a " @@ -1575,8 +1475,7 @@ msgid "You must have correct permissions to optimize the database." msgstr "Debes tener los permisos correctos para optimizar la base de datos." msgid "ERROR: Can not create temp directory for database building." -msgstr "" -"ERROR: No se pudo crear directorio temporal para crear la base de datos." +msgstr "ERROR: No se pudo crear directorio temporal para crear la base de datos." msgid "MD5sum'ing the old database..." msgstr "Calculando md5 de la base de datos antigua..." @@ -1606,11 +1505,10 @@ msgid "Finished. Your pacman database has been optimized." msgstr "Terminado, Tu base de datos pacman ha sido optimizada." msgid "For full benefits of pacman-optimize, run 'sync' now." -msgstr "" -"Para beneficiarse completamente de pacman-optimize ejecuta 'sync' ahora." +msgstr "Para beneficiarse completamente de pacman-optimize ejecuta 'sync' ahora." -msgid "Usage: %s <path-to-db> [--force] <package> ...\\n\\n" -msgstr "USO: %s <path-to-db> [--force] <package> ...\\n\\n" +msgid "Usage: %s [-q] <path-to-db> <package> ...\\n\\n" +msgstr "Uso: %s [-q] <ruta-a-bd> <paquete> ...\\n\\n" msgid "" "repo-add will update a package database by reading a package file." @@ -1621,25 +1519,21 @@ msgstr "" "\\n\\n" msgid "" -"The --force flag will add a 'force' entry to the sync database, which" -"\\ntells pacman to skip its internal version number checking and update" -"\\nthe package regardless.\\n\\n" -msgstr "" -"La opción --force añadirá una opción de forzar a la base de datos\\nque " -"obligará a pacman a saltarse la comprobación de la versión y actualizar\\nel " -"paquete de todas maneras.\\n\\n" +"The -q/--quiet flag will force this program to run silently except\\nin the " +"case of warnings or errors.\\n\\n" +msgstr "Las banderas -q/--quiet forzarán a este programa a trabajar en modo silencioso excepto \\nen el caso the advertencias o errores.\\n\\n" msgid "Example: repo-add /path/to/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz" msgstr "Ejemplo: repo-add /ruta/al/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz" msgid "" -"Copyright (C) 2006 Aaron Griffin <aaron@archlinux.org>.\\n\\nThis is free " -"software; see the source for copying conditions.\\nThere is NO WARRANTY, to " -"the extent permitted by law.\\n" +"Copyright (C) 2006-2008 Aaron Griffin <aaron@archlinux.org>.\\n\\nThis is " +"free software; see the source for copying conditions.\\nThere is NO " +"WARRANTY, to the extent permitted by law.\\n" msgstr "" -"Copyright (C) 2006 Aaron Griffin <aaron@archlinux.org>. \\n\\nEsto es " -"software libre, ver las fuentes para condiciones de copia.\\nNO HAY " -"GARANTÍA, hasta el extremo permitido por la ley.\\n" +"Derechos de copia (C) 2006 Aaron Griffin <aaron@archlinux.org>. \\n\\nEsto es " +"software libre, ver los fuentes para condiciones de copia.\\nNO HAY " +"GARANTÍA, a el grado permitido permitido por la ley.\\n" msgid "Invalid package file '%s'." msgstr "Paquete inalido '%s'." @@ -1671,6 +1565,12 @@ msgstr "%s no encontrado. No se puede continuar." msgid "Cannot create temp directory for database building." msgstr "No se puede crear directorio temp para la base de datos." +msgid "the -f and --force options are no longer recognized" +msgstr "las opciones -f and --force options ya no son reconocidas" + +msgid "use options=(force) in the PKGBUILD instead" +msgstr "use options=(force) in the PKGBUILD en su lugar" + msgid "Repository file '%s' is not a proper pacman database." msgstr "El archivo '%s' no es una base de datos pacman válida." @@ -1698,8 +1598,8 @@ msgstr "No se modificaron paquetes, nada que hacer." msgid "repo-remove %s\\n\\n" msgstr "repo-remove %s\\n\\n" -msgid "usage: %s <path-to-db> <packagename> ...\\n\\n" -msgstr "uso: %s <path-to-db> <packagename> ...\\n\\n" +msgid "usage: %s [-q] <path-to-db> <packagename> ...\\n\\n" +msgstr "uso: %s <ruta-a-bd> <nombre_de_paquete> ...\\n\\n" msgid "" "repo-remove will update a package database by removing the package name" @@ -1713,6 +1613,14 @@ msgstr "" msgid "Example: repo-remove /path/to/repo.db.tar.gz kernel26" msgstr "Ejemplo: repo-remove /path/al/repo.db.tar.gz kernel26" +msgid "" +"Copyright (c) 2007-2008 Dan McGee <dan@archlinux.org>.\\n\\nThis is free " +"software; see the source for copying conditions.\\nThere is NO WARRANTY, to " +"the extent permitted by law.\\n" +msgstr "" +"Derechos de copia (c) 2007-2008 Dan McGee <dan@archlinux.org>.\\n\\nEsto es software " +"libre; ver las fuentes para información de copia.\\nNO HAY GARANTÍA, al grado permitido por la ley.\\n" + msgid "Searching for package '%s'..." msgstr "Buscando el paquete '%s'..." @@ -1723,93 +1631,5 @@ msgid "Creating updated database file '%s'..." msgstr "Creando base de datos actualizada '%s'..." msgid "All packages have been removed from the database. Deleting '%s'." -msgstr "" -"Todos los paquetes han sido eliminados de la base de dtos. Eliminando '%s'." - -msgid "Usage: %s <action> <destfile> <option> [package_directory]" -msgstr "Uso: %s <action> <destfile> <option> [package_directory]" - -msgid "" -"updatesync will update a sync database by reading a PKGBUILD and\\nmodifying " -"the destfile. updatesync updates the database in a temporary\\ndirectory and " -"then compresses it to <destfile>.\\n\\n" -msgstr "" -"updatesync actualizará una base de datos leyendo un PKGBUILD y\\nmodificando " -"el destfile. updatesync actualiza la base de datos en un directorio temporal" -"\\n y entonces lo comprime en <destfile>.\\n\\n" - -msgid "There are two types of actions:\\n\\n" -msgstr "Hay dos tipos de acciones:\\n\\n" - -msgid "" -"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" -msgstr "" -"upd - Actualizará la entrada de un paquete o la creará si no existe.\\n " -"tome el PKGBUILD del paquete como una opción.\\n" - -msgid "" -"del - Will remove a package's entry from the db. It takes the package's" -"\\n name as an option.\\n" -msgstr "" -"del - Eliminará la entrada del paquete de la base de datos. toma el\\nnombre " -"del paquete como una opción.\\n" - -msgid "" -"updatesync will calculate md5sums of packages in the same directory as" -"\\n<destfile>, unless an alternate [package_directory] is specified.\\n\\n" -msgstr "" -"updatesync calculara el md5 de los paquetes en el mismo directorio que" -"\\n<destifle>, a menos que [package_directory] esté especificado.\\n\\n" - -msgid "Example: updatesync upd /home/mypkgs/custom.db.tar.gz PKGBUILD" -msgstr "Ejemplo: updatesync upd /home/mypkgs/custom.db.tar.gz PKGBUILD" - -msgid "" -"Copyright (C) 2004 Jason Chu <jason@archlinux.org>.\\n\\nThis is free " -"software; see the source for copying conditions.\\nThere is NO WARRANTY, to " -"the extent permitted by law.\\n" -msgstr "" -"Copyright (C) 2004 Jason Chu <jason@archlinux.org>.\\n\\nEsto es software " -"libre; ver las fuentes para información de copia.\\nNO HAY GARANTÍA hasta el " -"límite permitido por la ley.\\n" - -msgid "%s not found" -msgstr "%s no fue encontrado" - -msgid "could not find %s-%s-%s-%s%s - aborting" -msgstr "No se pudo encontrar %s-%s-%s-%s%s - abortando" - -#~ msgid "error: failed to add target '%s' (%s)" -#~ msgstr "error: fallo al procesar '%s' (%s)" - -#~ msgid ":: %s: conflicts with %s" -#~ msgstr ":: %s: posee conflictos con %s" - -#~ msgid "error: failed to add target '%s' (%s)\n" -#~ msgstr "error: fallo al procesar '%s' (%s)\n" - -#~ msgid "" -#~ ":: pacman has detected a newer version of itself.\n" -#~ ":: It is recommended that you upgrade pacman by itself\n" -#~ ":: using 'pacman -S pacman', and then rerun the current\n" -#~ ":: operation. If you wish to continue the operation and\n" -#~ ":: not upgrade pacman separately, answer no.\n" -#~ msgstr "" -#~ ":: Se ha encontrado una nueva versión de pacman.\n" -#~ ":: Se recomienda actualizar pacman\n" -#~ ":: usando 'pacman -S pacman', y ejecute nuevamente la\n" -#~ ":: operación. Si desea continuar con la operación y\n" -#~ ":: no actualizar pacman de forma separada, responda no.\n" - -#~ msgid ":: Cancel current operation? [Y/n] " -#~ msgstr ":: Cancelar la operación actual? [Y/n] " - -#~ msgid "debug: %s" -#~ msgstr "debug: %s" - -#~ msgid "debug: " -#~ msgstr "debug: " +msgstr "Todos los paquetes han sido eliminados de la base de dtos. Eliminando '%s'." -#~ msgid "--" -#~ msgstr "--" 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..e6c051b0 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -2,33 +2,36 @@ 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 +if USE_GIT_VERSION +GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 | sed s/^v//')-dirty +REAL_PACKAGE_VERSION = $(GIT_VERSION) +else +REAL_PACKAGE_VERSION = $(PACKAGE_VERSION) +endif + #### Taken from the autoconf scripts Makefile.am #### edit = sed \ -e 's|@localedir[@]|$(localedir)|g' \ -e 's|@sysconfdir[@]|$(sysconfdir)|g' \ -e 's|@localstatedir[@]|$(localstatedir)|g' \ -e 's|@prefix[@]|$(prefix)|g' \ - -e 's|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \ + -e 's|@PACKAGE_VERSION[@]|$(REAL_PACKAGE_VERSION)|g' \ -e 's|@PACKAGE_BUGREPORT[@]|$(PACKAGE_BUGREPORT)|g' \ -e 's|@PACKAGE_NAME[@]|$(PACKAGE_NAME)|g' \ -e 's|@DBEXT[@]|$(DBEXT)|g' \ @@ -48,13 +51,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 175edb8f..5bdc5bc9 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -33,18 +33,26 @@ export TEXTDOMAIN='pacman' export TEXTDOMAINDIR='@localedir@' +# file -i does not work on Mac OSX unless legacy mode is set +export COMMAND_MODE='legacy' + +# when fileglobbing, we want * in an empty directory to expand to the null +# string rather than itself +shopt -s nullglob + myver='@PACKAGE_VERSION@' confdir='@sysconfdir@' startdir="$PWD" srcdir="$startdir/src" pkgdir="$startdir/pkg" +known_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'ccache' 'distcc' 'makeflags' 'force') +readonly -a known_options # Options ASROOT=0 CLEANUP=0 CLEANCACHE=0 DEP_BIN=0 -DEP_SRC=0 FORCE=0 INFAKEROOT=0 GENINTEG=0 @@ -182,25 +190,6 @@ check_option() { return fi - # BEGIN DEPRECATED - # TODO: This code should be removed in the next release of makepkg. - local needle=$(echo $1 | tr [:upper:] [:lower:]) - local opt - for opt in ${options[@]}; do - opt=$(echo $opt | tr [:upper:] [:lower:]) - if [ "$opt" = "no$needle" ]; then - warning "$(gettext "Options beginning with 'no' will be deprecated in the next version of makepkg!")" - plain "$(gettext "Please replace 'no' with '!': %s -> %s.")" "no$needle" "!$needle" - echo 'n' # Disabled - return - elif [ "$opt" = "keepdocs" -a "$needle" = "docs" ]; then - warning "$(gettext "Option 'keepdocs' may not work as intended. Please replace with 'docs'.")" - echo 'y' # Enabled - return - fi - done - # END DEPRECATED - # fall back to makepkg.conf options ret=$(in_opt_array "$1" ${OPTIONS[@]}) if [ "$ret" != '?' ]; then @@ -299,6 +288,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 @@ -325,7 +328,7 @@ handledeps() { striplist="$striplist $depstrip" done - if [ "$DEP_SRC" = "0" -a "$DEP_BIN" = "0" ]; then + if [ "$DEP_BIN" = "0" ]; then return $R_DEPS_MISSING fi @@ -344,40 +347,6 @@ handledeps() { error "$(gettext "Pacman failed to install missing dependencies.")" exit 1 # TODO: error code fi - elif [ "$DEP_SRC" = "1" ]; then - msg "$(gettext "Building missing dependencies...")" - - # install missing deps by building them from source. - # we look for each package name in $SRCROOT and build it. - if [ "$SRCROOT" = "" ]; then - error "$(gettext "Source root cannot be found - please make sure it is specified in %s.")" "$confdir/makepkg.conf" - exit 1 # TODO: error code - fi - - # TODO: handle version comparators (eg, glibc>=2.2.5) - for dep in $striplist; do - local candidates="$(find "$SRCROOT" -type d -name "$dep")" - if [ "$candidates" = "" ]; then - error "$(gettext "Could not find '%s' under %s")" "$dep" "$SRCROOT" - exit 1 # TODO: error code - fi - - local makepkg_opts='-i -c -b' - [ "$RMDEPS" = "1" ] && makepkg_opts="$makepkg_opts -r" - [ "$ASROOT" = "1" ] && makepkg_opts="$makepkg_opts --asroot" - local ret packagedir - for packagedir in $candidates; do - if [ -f "$packagedir/$BUILDSCRIPT" ]; then - cd "$packagedir" - ret=0 - PKGDEST="$PKGDEST" makepkg $makepkg_opts $PACMAN_OPTS || ret=$? - [ $ret -eq 0 ] && continue 2 - fi - done - - error "$(gettext "Failed to build '%s'")" "$dep" - exit 1 # TODO: error code - done fi # rerun any additional sh scripts found in /etc/profile.d/ @@ -407,7 +376,7 @@ resolve_deps() { # check deps again to make sure they were resolved deplist="$(check_deps $*)" [ "$deplist" = "" ] && return $R_DEPS_SATISFIED - elif [ "$DEP_BIN" = "1" -o "$DEP_SRC" = "1" ]; then + elif [ "$DEP_BIN" = "1" ]; then error "$(gettext "Failed to install all missing dependencies.")" fi @@ -433,10 +402,17 @@ remove_deps() { done msg "Removing installed dependencies..." + local ret=0 if [ "$ASROOT" = "0" ]; then - sudo pacman $PACMAN_OPTS -Rns $deplist + sudo pacman $PACMAN_OPTS -Rns $deplist || ret=$? else - pacman $PACMAN_OPTS -Rns $deplist + pacman $PACMAN_OPTS -Rns $deplist || ret=$? + fi + + # Fixes FS#10039 - exit cleanly as package has built successfully + if [ $ret -ne 0 ]; then + warning "$(gettext "Failed to remove installed dependencies.")" + return 0 fi } @@ -456,11 +432,13 @@ download_sources() { local file=$(strip_url "$netfile") if [ -f "$startdir/$file" ]; then msg2 "$(gettext "Found %s in build dir")" "$file" - cp -s --remove-destination "$startdir/$file" "$srcdir/" + rm -f "$srcdir/$file" + ln -s "$startdir/$file" "$srcdir/" continue elif [ -f "$SRCDEST/$file" ]; then msg2 "$(gettext "Using cached copy of %s")" "$file" - cp -s --remove-destination "$SRCDEST/$file" "$srcdir/" + rm -f "$srcdir/$file" + ln -s "$SRCDEST/$file" "$srcdir/" continue fi @@ -471,18 +449,22 @@ 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 - cp -s --remove-destination "$SRCDEST/$file" "$srcdir/" + if echo "$dlclient" | grep -q "%o" ; then + mv -f "$SRCDEST/$file.part" "$SRCDEST/$file" + fi + rm -f "$srcdir/$file" + ln -s "$SRCDEST/$file" "$srcdir/" done popd &>/dev/null @@ -647,8 +629,8 @@ extract_sources() { done if [ $EUID -eq 0 ]; then - # chown all source files to root.root - chown -R root.root "$srcdir" + # change perms of all source files to root user & root group + chown -R 0:0 "$srcdir" fi } @@ -716,37 +698,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 @@ -790,7 +776,7 @@ create_package() { else local packager="Unknown Packager" fi - local size=$(du -sb | awk '{print $1}') + local size=$(du -sk | awk '{print $1 * 1024}') # write the .PKGINFO file msg2 "$(gettext "Generating .PKGINFO file...")" @@ -849,7 +835,6 @@ create_package() { local comp_files=".PKGINFO" # check for an install script - # TODO: should we include ${pkgname}.install if it exists and $install is unset? if [ "$install" != "" ]; then msg2 "$(gettext "Adding install script...")" cp "$startdir/$install" .INSTALL @@ -868,7 +853,7 @@ create_package() { local pkg_file="$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" - if ! bsdtar -czf "$pkg_file" $comp_files $(ls); then + if ! bsdtar -czf "$pkg_file" $comp_files *; then error "$(gettext "Failed to create package file.")" exit 1 # TODO: error code fi @@ -940,14 +925,26 @@ create_xdelta() { create_srcpackage() { cd "$startdir" + if [ "$SOURCEONLY" = "2" ]; then + # get back to our src directory so we can begin with sources + mkdir -p "$srcdir" + cd "$srcdir" + download_sources + # we can only check checksums if we have all files + check_checksums + cd "$startdir" + fi msg "$(gettext "Creating source package...")" - local comp_files="$BUILDSCRIPT" + local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)" + mkdir "${srclinks}"/${pkgname} + msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" + ln -s "${startdir}/${BUILDSCRIPT}" "${srclinks}/${pkgname}/" if [ "$install" != "" ]; then if [ -f $install ]; then msg2 "$(gettext "Adding install script...")" - comp_files="$comp_files $install" + ln -s "${startdir}/$install" "${srclinks}/${pkgname}/" else error "$(gettext "Install script %s not found.")" "$install" fi @@ -955,14 +952,18 @@ create_srcpackage() { if [ -f ChangeLog ]; then msg2 "$(gettext "Adding %s...")" "ChangeLog" - comp_files="$comp_files ChangeLog" + ln -s "${startdir}/ChangeLog" "${srclinks}/${pkgname}" fi - local i - for i in ${source[@]}; do - if [ -f $i ]; then - msg2 "$(gettext "Adding %s...")" "$i" - comp_files="$comp_files $i" + local netfile + for netfile in ${source[@]}; do + local file=$(strip_url "$netfile") + if [ -f $netfile ]; then + msg2 "$(gettext "Adding %s...")" "$netfile" + ln -s $netfile ${srclinks}/${pkgname} + elif [ "$SOURCEONLY" = "2" -a -f "$SRCDEST/$file" ]; then + msg2 "$(gettext "Adding %s...")" "$file" + ln -s "$SRCDEST/$file" "${srclinks}/${pkgname}/" fi done @@ -970,10 +971,13 @@ create_srcpackage() { # tar it up msg2 "$(gettext "Compressing source package...")" - if ! bsdtar -czf "$pkg_file" $comp_files; then + cd ${srclinks} + if ! bsdtar -czLf "$pkg_file" ${pkgname}; then error "$(gettext "Failed to create source package file.")" exit 1 # TODO: error code fi + cd ${startdir} + rm -rf ${srclinks} } install_package() { @@ -1071,7 +1075,6 @@ usage() { echo echo "$(gettext "Options:")" printf "$(gettext " -A, --ignorearch Ignore incomplete arch field in %s")\n" "$BUILDSCRIPT" - echo "$(gettext " -b, --builddeps Build missing dependencies from source")" echo "$(gettext " -c, --clean Clean up work files after build")" echo "$(gettext " -C, --cleancache Clean up source files from the cache")" echo "$(gettext " -d, --nodeps Skip all dependency checks")" @@ -1145,9 +1148,11 @@ SRCDEST=${_SRCDEST:-$SRCDEST} SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined # Parse Command Line Options. -OPT_SHORT="AbcCdefFghiLmop:rRsSV" -OPT_LONG="ignorearch,asroot,builddeps,clean,cleancache,nodeps,noextract,force,forcever:,geninteg,help,holdver" -OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,rmdeps,repackage,source,syncdeps,usesudo,version" +OPT_SHORT="AbcCdefFghiLmop:rRsV" +OPT_LONG="allsource,asroot,ignorearch,builddeps,clean,cleancache,nodeps" +OPT_LONG="$OPT_LONG,noextract,force,forcever:,geninteg,help,holdver" +OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,rmdeps,repackage,source" +OPT_LONG="$OPT_LONG,syncdeps,version" # Pacman Options OPT_LONG="$OPT_LONG,noconfirm,noprogressbar" OPT_TEMP="$(getopt -o "$OPT_SHORT" -l "$OPT_LONG" -n "$(basename "$0")" -- "$@" || echo 'GETOPT GO BANG!')" @@ -1165,9 +1170,9 @@ while true; do --noprogressbar) PACMAN_OPTS="$PACMAN_OPTS --noprogressbar" ;; # Makepkg Options + --allsource) SOURCEONLY=2 ;; --asroot) ASROOT=1 ;; -A|--ignorearch) IGNOREARCH=1 ;; - -b|--builddeps) DEP_SRC=1 ;; -c|--clean) CLEANUP=1 ;; -C|--cleancache) CLEANCACHE=1 ;; -d|--nodeps) NODEPS=1 ;; @@ -1188,11 +1193,6 @@ while true; do --source) SOURCEONLY=1 ;; -s|--syncdeps) DEP_BIN=1 ;; - # BEGIN DEPRECATED - -S|--usesudo) - warning "$(gettext "Sudo is used by default now. The --usesudo option is deprecated!")" ;; - # END DEPRECATED - -h|--help) usage; exit 0 ;; # E_OK -V|--version) version; exit 0 ;; # E_OK @@ -1276,7 +1276,7 @@ else fi # check for sudo if we will need it during makepkg execution -if [ "$ASROOT" = "0" -a \( "$DEP_BIN" = "1" -o "$DEP_SRC" = "1" \ +if [ "$ASROOT" = "0" -a \( "$DEP_BIN" = "1" \ -o "$RMDEPS" = "1" -o "$INSTALL" = "1" \) ]; then if [ ! "$(type -p sudo)" ]; then error "$(gettext "Cannot find the sudo binary! Is sudo installed?")" @@ -1293,13 +1293,6 @@ unset optdepends options noextract if [ ! -f "$BUILDSCRIPT" ]; then error "$(gettext "%s does not exist.")" "$BUILDSCRIPT" exit 1 - #TODO this is an attempt at a generic way to unset all package specific - #variables in a PKGBUILD - #else - # #this is fun.... we'll unset - # for var in $(grep "=" $BUILDSCRIPT | sed "s|.*\(\<.*\>\)=.*|\1|g"); do - # unset $var - # done fi source "$BUILDSCRIPT" @@ -1348,6 +1341,25 @@ if [ "$install" -a ! -f "$install" ]; then exit 1 fi +valid_options=1 +for opt in ${options[@]}; do + known=0 + # check if option matches a known option or its inverse + for kopt in ${known_options[@]}; do + if [ "${opt}" = "${kopt}" -o "${opt}" = "!${kopt}" ]; then + known=1 + fi + done + if [ $known -eq 0 ]; then + error "$(gettext "options array contains unknown option '%s'")" "$opt" + valid_options=0 + fi +done +if [ $valid_options -eq 0 ]; then + exit 1 +fi +unset valid_options opt known kopt + # We need to run devel_update regardless of whether we are in the fakeroot # build process so that if the user runs makepkg --forcever manually, we # 1) output the correct pkgver, and 2) use the correct filename when @@ -1383,14 +1395,14 @@ if [ "$INFAKEROOT" = "1" ]; then exit 0 # $E_OK fi -msg "$(gettext "Making package: %s")" "$pkgname $pkgver-$pkgrel ($(date))" +msg "$(gettext "Making package: %s")" "$pkgname $pkgver-$pkgrel $CARCH ($(date))" if [ $EUID -eq 0 ]; then warning "$(gettext "Running makepkg as root...")" fi # if we are creating a source-only package, go no further -if [ "$SOURCEONLY" = "1" ]; then +if [ "$SOURCEONLY" != "0" ]; then if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}${SRCEXT}" \ -a "$FORCE" = "0" ]; then error "$(gettext "A package has already been built. (use -f to overwrite)")" @@ -1470,8 +1482,8 @@ else mkdir -p "$pkgdir" cd "$startdir" - if [ $EUID -eq 0 ]; then - # if we are root, then we don't need to recall makepkg with fakeroot + if [ "$(check_buildenv fakeroot)" != "y" -o $EUID -eq 0 ]; then + # if we are root or if fakeroot is not enabled, then we don't use it if [ "$REPKG" = "1" ]; then warning "$(gettext "Skipping build.")" else @@ -1494,7 +1506,7 @@ else create_xdelta "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" fi -msg "$(gettext "Finished making: %s")" "$pkgname ($(date))" +msg "$(gettext "Finished making: %s")" "$pkgname $pkgver-$pkgrel $CARCH ($(date))" install_package diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index 63d94d37..e90f0e89 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -3,7 +3,7 @@ # repo-add - add a package to a given repo database file # @configure_input@ # -# Copyright (c) 2006 Aaron Griffin <aaron@archlinux.org> +# Copyright (c) 2006-2008 Aaron Griffin <aaron@archlinux.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 @@ -25,18 +25,20 @@ export TEXTDOMAINDIR='@localedir@' myver='@PACKAGE_VERSION@' confdir='@sysconfdir@' -FORCE=0 +QUIET=0 REPO_DB_FILE="" # ensure we have a sane umask set umask 0022 msg() { + [ $QUIET -ne 0 ] && return local mesg=$1; shift printf "==> ${mesg}\n" "$@" >&1 } msg2() { + [ $QUIET -ne 0 ] && return local mesg=$1; shift printf " -> ${mesg}\n" "$@" >&1 } @@ -54,21 +56,20 @@ 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 [-q] <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")" +The -q/--quiet flag will force this program to run silently except\n\ +in the case of warnings or errors.\n\n")" echo "$(gettext "Example: repo-add /path/to/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz")" } version() { printf "repo-add (pacman) %s\n" "$myver" printf "$(gettext "\ -Copyright (C) 2006 Aaron Griffin <aaron@archlinux.org>.\n\n\ +Copyright (C) 2006-2008 Aaron Griffin <aaron@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")" } @@ -117,7 +118,7 @@ db_write_delta() # get md5sum and size of delta md5sum="$(md5sum "$deltafile" | cut -d ' ' -f 1)" - csize=$(du -b -L "$deltafile" | cut -f 1) + csize=$(du -kL "$deltafile" | awk '{print $1 * 1024}') # ensure variables were found if [ -z "$pkgname" -o -z "$fromver" -o -z "$tover" -o -z "$arch" ]; then @@ -164,7 +165,7 @@ db_write_entry() IFS=$OLDIFS # get compressed size of package - csize=$(du -b -L "$pkgfile" | cut -f 1) + csize=$(du -kL "$pkgfile" | awk '{print $1 * 1024}') startdir=$(pwd) pushd "$gstmpdir" 2>&1 >/dev/null @@ -209,7 +210,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...")" @@ -236,7 +237,7 @@ db_write_entry() if db_write_delta "$delta"; then msg2 "$(gettext "Added delta '%s'")" "$(basename "$delta")" else - msg2 "$(gettext "Could not add delta '%s'")" "$(basename "$delta")" + warning "$(gettext "Could not add delta '%s'")" "$(basename "$delta")" fi fi done @@ -298,7 +299,10 @@ 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 [ "$arg" == "--quiet" -o "$arg" == "-q" ]; then + QUIET=1 elif [ -z "$REPO_DB_FILE" ]; then REPO_DB_FILE=$(readlink -f "$arg") if ! test_repo_db_file; then diff --git a/scripts/repo-remove.sh.in b/scripts/repo-remove.sh.in index 47a0d5ae..08786eec 100644 --- a/scripts/repo-remove.sh.in +++ b/scripts/repo-remove.sh.in @@ -3,7 +3,7 @@ # repo-remove - remove a package entry from a given repo database file # @configure_input@ # -# Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> +# Copyright (c) 2007-2008 Dan McGee <dan@archlinux.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 @@ -25,14 +25,17 @@ export TEXTDOMAINDIR='@localedir@' myver='@PACKAGE_VERSION@' confdir='@sysconfdir@' +QUIET=0 REPO_DB_FILE="" msg() { + [ $QUIET -ne 0 ] && return local mesg=$1; shift printf "==> ${mesg}\n" "$@" >&1 } msg2() { + [ $QUIET -ne 0 ] && return local mesg=$1; shift printf " -> ${mesg}\n" "$@" >&1 } @@ -50,18 +53,21 @@ error() { # print usage instructions usage() { printf "$(gettext "repo-remove %s\n\n")" $myver - printf "$(gettext "usage: %s <path-to-db> <packagename> ...\n\n")" "$0" + printf "$(gettext "usage: %s [-q] <path-to-db> <packagename> ...\n\n")" "$0" printf "$(gettext "\ repo-remove will update a package database by removing the package name\n\ specified on the command line from the given repo database. Multiple\n\ packages to remove can be specified on the command line.\n\n")" + printf "$(gettext "\ +The -q/--quiet flag will force this program to run silently except\n\ +in the case of warnings or errors.\n\n")" echo "$(gettext "Example: repo-remove /path/to/repo.db.tar.gz kernel26")" } version() { printf "repo-remove (pacman) %s\n" "$myver" printf "$(gettext "\ -Copyright (C) 2002-2007 Judd Vinet <jvinet@zeroflux.org>.\n\n\ +Copyright (c) 2007-2008 Dan McGee <dan@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")" } @@ -140,7 +146,9 @@ gstmpdir=$(mktemp -d /tmp/repo-remove.XXXXXXXXXX) || (\ success=0 # parse arguments for arg in "$@"; do - if [ -z "$REPO_DB_FILE" ]; then + if [ "$arg" == "--quiet" -o "$arg" == "-q" ]; then + QUIET=1 + elif [ -z "$REPO_DB_FILE" ]; then REPO_DB_FILE=$(readlink -f "$arg") if ! test_repo_db_file; then error "$(gettext "Repository file '%s' is not a proper pacman database.")\n" "$REPO_DB_FILE" diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am index 5e287404..e5f8cb36 100644 --- a/src/pacman/Makefile.am +++ b/src/pacman/Makefile.am @@ -21,8 +21,12 @@ INCLUDES = -I$(top_srcdir)/lib/libalpm AM_CFLAGS = -pedantic -D_GNU_SOURCE +if USE_GIT_VERSION +GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 | sed s/^v//')-dirty +DEFS += -DGIT_VERSION=\"$(GIT_VERSION)\" +endif + pacman_SOURCES = \ - add.c \ conf.h conf.c \ deptest.c \ package.h package.c \ @@ -31,6 +35,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..ff125c36 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <string.h> #include <sys/time.h> +#include <sys/types.h> /* off_t */ #include <unistd.h> #include <dirent.h> #include <wchar.h> @@ -34,12 +35,11 @@ #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; +static off_t xfered_last; +static off_t list_xfered = 0.0; +static off_t list_total = 0.0; static struct timeval initial_time; /* transaction progress bar */ @@ -86,17 +86,15 @@ 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, +static void fill_progress(const int bar_percent, const int disp_percent, const int proglen) { const unsigned int hashlen = proglen - 8; - const unsigned int hash = graph_percent * hashlen / 100; + const unsigned int hash = bar_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(bar_percent == 0) { lasthash = 0; mouth = 0; } @@ -141,10 +139,12 @@ static void fill_progress(const int graph_percent, const int display_percent, } /* print percent after progress bar */ if(proglen > 5) { - printf(" %3d%%", display_percent); + /* use disp_percent if it is not 0, else show bar_percent */ + int p = disp_percent ? disp_percent : bar_percent; + printf(" %3d%%", p); } - if(graph_percent == 100) { + if(bar_percent == 100) { printf("\n"); } else { printf("\r"); @@ -157,8 +157,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 +178,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 +188,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 +198,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")); @@ -237,7 +232,6 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) break; /* all the simple done events, with fallthrough for each */ case PM_TRANS_EVT_FILECONFLICTS_DONE: - case PM_TRANS_EVT_EXTRACT_DONE: case PM_TRANS_EVT_CHECKDEPS_DONE: case PM_TRANS_EVT_RESOLVEDEPS_DONE: case PM_TRANS_EVT_INTERCONFLICTS_DONE: @@ -255,67 +249,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; } } @@ -442,9 +415,19 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent, } } +/* callback to handle receipt of total download value */ +void cb_dl_total(off_t total) +{ + list_total = total; + /* if we get a 0 value, it means this list has finished downloading, + * so clear out our list_xfered as well */ + if(total == 0) { + list_xfered = 0; + } +} + /* 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, off_t file_xfered, off_t file_total) { const int infolen = 50; const int filenamelen = infolen - 27; @@ -453,44 +436,37 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, int len, wclen, wcwid, padwid; wchar_t *wcfname; + off_t xfered, 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 file_percent = 0, total_percent = 0; 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; + /* only use TotalDownload if enabled and we have a callback value */ + if(config->totaldownload && list_total) { + xfered = list_xfered + file_xfered; total = list_total; } else { xfered = file_xfered; total = file_total; } - /* this is basically a switch on file_xferred: 0, file_total, and + /* this is basically a switch on xfered: 0, 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)) { + /* set default starting values, ensure we only call this once + * if TotalDownload is enabled */ + if(!(config->totaldownload) + || (config->totaldownload && list_xfered == 0)) { gettimeofday(&initial_time, NULL); - timediff = get_update_timediff(1); - xfered_last = 0; + xfered_last = (off_t)0; rate_last = 0.0; - has_init = 1; + timediff = get_update_timediff(1); } - rate = 0.0; - eta_s = 0; } else if(file_xfered == file_total) { /* compute final values */ struct timeval current_time; @@ -514,12 +490,24 @@ 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; } + file_percent = (int)((float)file_xfered) / ((float)file_total) * 100; + + if(config->totaldownload && list_total) { + total_percent = (int)((float)list_xfered + file_xfered) / + ((float)list_total) * 100; + + /* if we are at the end, add the completed file to list_xfered */ + if(file_xfered == file_total) { + list_xfered += file_total; + } + } + /* fix up time for display */ eta_h = eta_s / 3600; eta_s -= eta_h * 3600; @@ -591,11 +579,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(file_percent, total_percent, getcols() - infolen); return; } diff --git a/src/pacman/callback.h b/src/pacman/callback.h index aa8d9370..2961be84 100644 --- a/src/pacman/callback.h +++ b/src/pacman/callback.h @@ -19,6 +19,8 @@ #ifndef _PM_CALLBACK_H #define _PM_CALLBACK_H +#include <sys/types.h> /* off_t */ + #include <alpm.h> /* callback to handle messages/notifications from libalpm transactions */ @@ -32,9 +34,10 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent, int howmany, int remain); +/* callback to handle receipt of total download value */ +void cb_dl_total(off_t total); /* 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, off_t file_xfered, off_t 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.c b/src/pacman/conf.c index bf3a4624..48c927bf 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -25,6 +25,7 @@ /* pacman */ #include "conf.h" +#include "util.h" /* global config variable */ config_t *config = NULL; @@ -33,8 +34,9 @@ config_t *config_new(void) { config_t *newconfig = calloc(1, sizeof(config_t)); if(!newconfig) { - fprintf(stderr, "malloc failure: could not allocate %zd bytes\n", - sizeof(config_t)); + pm_fprintf(stderr, PM_LOG_ERROR, + _("malloc failure: could not allocate %zd bytes\n"), + sizeof(config_t)); return(NULL); } /* defaults which may get overridden later */ @@ -45,6 +47,7 @@ config_t *config_new(void) newconfig->rootdir = NULL; newconfig->dbpath = NULL; newconfig->logfile = NULL; + newconfig->syncfirst = NULL; return(newconfig); } @@ -55,6 +58,7 @@ int config_free(config_t *oldconfig) return(-1); } + FREELIST(oldconfig->syncfirst); free(oldconfig->configfile); free(oldconfig->rootdir); free(oldconfig->dbpath); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index f804f560..874ce708 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,16 @@ 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 */ + alpm_list_t *syncfirst; } config_t; /* Operations */ enum { PM_OP_MAIN = 1, - PM_OP_ADD, PM_OP_REMOVE, PM_OP_UPGRADE, PM_OP_QUERY, @@ -83,6 +82,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/package.c b/src/pacman/package.c index 7019e7e6..1698806f 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -90,9 +90,6 @@ void dump_pkg_full(pmpkg_t *pkg, int level) } /* actual output */ - if(level == 0) { - string_display(_("Filename :"), alpm_pkg_get_filename(pkg)); - } string_display(_("Name :"), alpm_pkg_get_name(pkg)); string_display(_("Version :"), alpm_pkg_get_version(pkg)); string_display(_("URL :"), alpm_pkg_get_url(pkg)); @@ -195,8 +192,8 @@ void dump_pkg_backups(pmpkg_t *pkg) char *md5sum = alpm_get_md5sum(path); if(md5sum == NULL) { - fprintf(stderr, _("error: could not calculate checksums for %s\n"), - path); + pm_fprintf(stderr, PM_LOG_ERROR, + _("could not calculate checksums for %s\n"), path); free(str); continue; } @@ -225,17 +222,14 @@ void dump_pkg_files(pmpkg_t *pkg) { const char *pkgname, *root, *filestr; alpm_list_t *i, *pkgfiles; - char path[PATH_MAX]; pkgname = alpm_pkg_get_name(pkg); pkgfiles = alpm_pkg_get_files(pkg); root = alpm_option_get_root(); for(i = pkgfiles; i; i = alpm_list_next(i)) { - filestr = (char*)alpm_list_getdata(i); - /* build a path so we can stat the filename */ - snprintf(path, PATH_MAX-1, "%s%s", root, filestr); - fprintf(stdout, "%s %s\n", pkgname, path); + filestr = alpm_list_getdata(i); + fprintf(stdout, "%s %s%s\n", pkgname, root, filestr); } fflush(stdout); @@ -248,8 +242,7 @@ void dump_pkg_changelog(pmpkg_t *pkg) void *fp = NULL; if((fp = alpm_pkg_changelog_open(pkg)) == NULL) { - /* TODO after string freeze use pm_fprintf */ - fprintf(stderr, _("error: no changelog available for '%s'.\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("no changelog available for '%s'.\n"), alpm_pkg_get_name(pkg)); return; } else { diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index c2b61fcd..813a7284 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -19,6 +19,12 @@ #include "config.h" +/* special handling of package version for GIT */ +#if defined(GIT_VERSION) +#undef PACKAGE_VERSION +#define PACKAGE_VERSION GIT_VERSION +#endif + #include <stdlib.h> /* atoi */ #include <stdio.h> #include <limits.h> @@ -68,31 +74,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 +117,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")); @@ -151,11 +153,11 @@ static void version(void) { printf("\n"); printf(" .--. Pacman v%s - libalpm v%s\n", PACKAGE_VERSION, alpm_version()); - printf("/ _.-' .-. .-. .-. Copyright (C) 2002-2008 Judd Vinet <jvinet@zeroflux.org>\n"); - printf("\\ '-. '-' '-' '-'\n"); + printf("/ _.-' .-. .-. .-. Copyright (C) 2006-2008 Dan McGee <dan@archlinux.org>\n"); + printf("\\ '-. '-' '-' '-' Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>\n"); printf(" '--'\n"); printf(_(" This program may be freely redistributed under\n" - " the terms of the GNU General Public License\n")); + " the terms of the GNU General Public License.\n")); printf("\n"); } @@ -212,14 +214,15 @@ 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) { /* write a log message and write to stderr */ - pm_printf(PM_LOG_ERROR, "segmentation fault\n"); - pm_fprintf(stderr, PM_LOG_ERROR, "Internal pacman error: Segmentation fault.\n" - "Please submit a full bug report with --debug if appropriate.\n"); + pm_printf(PM_LOG_ERROR, _("segmentation fault\n")); + pm_fprintf(stderr, PM_LOG_ERROR, + _("Internal pacman error: Segmentation fault.\n" + "Please submit a full bug report with --debug if appropriate.\n")); exit(signum); } else if((signum == SIGINT)) { if(alpm_trans_interrupt() == 0) { @@ -305,7 +308,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 +320,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 +339,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 +354,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 +426,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 +449,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 +472,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 +484,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': @@ -512,6 +521,11 @@ static int parseargs(int argc, char *argv[]) return(0); } +/* helper for being used with setrepeatingoption */ +static void option_add_syncfirst(const char *name) { + config->syncfirst = alpm_list_add(config->syncfirst, strdup(name)); +} + /** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm * settings. Refactored out of the parseconfig code since all of them did * the exact same thing and duplicated code. @@ -599,7 +613,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 +626,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 +634,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 +662,66 @@ 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, "SyncFirst") == 0) { + setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst); + } 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 +737,6 @@ static int _parseconfig(const char *file, const char *givensection, return(1); } } - free(upperkey); } } fclose(fp); @@ -753,7 +769,7 @@ int main(int argc, char *argv[]) { int ret = 0; struct sigaction new_action, old_action; -#if defined(HAVE_GETEUID) +#if defined(HAVE_GETEUID) && !defined(CYGWIN) /* geteuid undefined in CYGWIN */ uid_t myuid = geteuid(); #endif @@ -834,7 +850,12 @@ int main(int argc, char *argv[]) cleanup(ret); } -#if defined(HAVE_GETEUID) + /* set TotalDownload callback if option enabled */ + if(config->totaldownload) { + alpm_option_set_totaldlcb(cb_dl_total); + } + +#if defined(HAVE_GETEUID) && !defined(CYGWIN) /* check if we have sufficient permission for the requested operation */ if(myuid > 0 && needs_transaction()) { pm_printf(PM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n")); @@ -867,9 +888,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..74d3ff21 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 @@ -62,28 +62,28 @@ static int query_fileowner(alpm_list_t *targets) /* This code is here for safety only */ if(targets == NULL) { - fprintf(stderr, _("error: no file was specified for --owns\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("no file was specified for --owns\n")); return(1); } for(t = targets; t; t = alpm_list_next(t)) { int found = 0; char *filename = alpm_list_getdata(t); - char *bname; - char *dname; - char *rpath; + char *bname, *dname, *rpath; + const char *root; struct stat buf; alpm_list_t *i, *j; if(stat(filename, &buf) == -1) { - fprintf(stderr, _("error: failed to read file '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"), filename, strerror(errno)); ret++; continue; } if(S_ISDIR(buf.st_mode)) { - fprintf(stderr, _("error: cannot determine ownership of a directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, + _("cannot determine ownership of a directory\n")); ret++; continue; } @@ -94,20 +94,22 @@ static int query_fileowner(alpm_list_t *targets) free(dname); if(!rpath) { - fprintf(stderr, _("error: cannot determine real path for '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("cannot determine real path for '%s': %s\n"), filename, strerror(errno)); free(rpath); ret++; continue; } + root = alpm_option_get_root(); + for(i = alpm_db_getpkgcache(db_local); i && !found; i = alpm_list_next(i)) { pmpkg_t *info = alpm_list_getdata(i); for(j = alpm_pkg_get_files(info); j && !found; j = alpm_list_next(j)) { char path[PATH_MAX], *ppath, *pdname; snprintf(path, PATH_MAX, "%s%s", - alpm_option_get_root(), (const char *)alpm_list_getdata(j)); + root, (const char *)alpm_list_getdata(j)); /* avoid the costly resolve_path usage if the basenames don't match */ if(strcmp(mbasename(path), bname) != 0) { @@ -119,15 +121,20 @@ 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); } } if(!found) { - fprintf(stderr, _("error: No package owns %s\n"), filename); + pm_fprintf(stderr, PM_LOG_ERROR, _("No package owns %s\n"), filename); ret++; } free(rpath); @@ -155,7 +162,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 +182,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 +212,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); + pm_fprintf(stderr, PM_LOG_ERROR, _("group \"%s\" was not found\n"), grpname); ret++; } } @@ -401,7 +416,7 @@ int pacman_query(alpm_list_t *targets) } if(pkg == NULL) { - fprintf(stderr, _("error: package \"%s\" not found\n"), strname); + pm_fprintf(stderr, PM_LOG_ERROR, _("package \"%s\" not found\n"), strname); ret++; continue; } diff --git a/src/pacman/remove.c b/src/pacman/remove.c index e3750e4c..4fe9bc81 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); } @@ -107,9 +86,9 @@ int pacman_remove(alpm_list_t *targets) for(i = finaltargs; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); if(alpm_trans_addtarget(targ) == -1) { - fprintf(stderr, _("error: '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); - remove_cleanup(); + trans_release(); FREELIST(finaltargs); return(1); } @@ -117,7 +96,7 @@ int pacman_remove(alpm_list_t *targets) /* Step 2: prepare the transaction based on its type, targets and flags */ if(alpm_trans_prepare(&data) == -1) { - fprintf(stderr, _("error: failed to prepare transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { case PM_ERR_UNSATISFIED_DEPS: @@ -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); } @@ -163,15 +142,17 @@ int pacman_remove(alpm_list_t *targets) /* Step 3: actually perform the removal */ if(alpm_trans_commit(NULL) == -1) { - fprintf(stderr, _("error: failed to commit transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_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..47ab4ebb 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; @@ -50,7 +46,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { dir = opendir(dbpath); if(dir == NULL) { - fprintf(stderr, _("error: could not access database directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not access database directory\n")); return(1); } @@ -61,7 +57,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { struct stat buf; alpm_list_t *syncdbs = NULL, *i; int found = 0; - char *dname = ent->d_name; + const char *dname = ent->d_name; if(!strcmp(dname, ".") || !strcmp(dname, "..")) { continue; @@ -72,7 +68,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { } /* build the full path */ - snprintf(path, PATH_MAX, "%s%s", dbpath, ent->d_name); + snprintf(path, PATH_MAX, "%s%s", dbpath, dname); /* skip entries that are not dirs (lock file, etc.) */ stat(path, &buf); if(!S_ISDIR(buf.st_mode)) { @@ -89,12 +85,13 @@ 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; } if(rmrf(path)) { - fprintf(stderr, _("error: could not remove repository directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, + _("could not remove repository directory\n")); return(1); } } @@ -108,7 +105,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,19 +130,29 @@ 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... ")); dir = opendir(cachedir); if(dir == NULL) { - fprintf(stderr, _("error: could not access cache directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not access cache directory\n")); return(1); } @@ -153,13 +160,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,36 +177,56 @@ 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... ")); if(rmrf(cachedir)) { - fprintf(stderr, _("error: could not remove cache directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove cache directory\n")); return(1); } if(makepath(cachedir)) { - fprintf(stderr, _("error: could not create new cache directory\n")); + pm_fprintf(stderr, PM_LOG_ERROR, _("could not create new cache directory\n")); return(1); } printf(_("done.\n")); @@ -205,52 +235,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()); - } + pm_fprintf(stderr, PM_LOG_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 +259,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) { + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to synchronize any databases\n")); + } return(success > 0); } @@ -289,8 +295,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 +315,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,19 +345,21 @@ 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; if(targets) { for(i = targets; i; i = alpm_list_next(i)) { - char *grpname = alpm_list_getdata(i); + const char *grpname = alpm_list_getdata(i); for(j = syncs; j; j = alpm_list_next(j)) { pmdb_t *db = alpm_list_getdata(j); 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)) { + printf("%s %s\n", grpname, + alpm_pkg_get_name(alpm_list_getdata(k))); + } } } } @@ -354,10 +369,16 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) for(j = alpm_db_getgrpcache(db); j; j = alpm_list_next(j)) { pmgrp_t *grp = alpm_list_getdata(j); + const char *grpname = alpm_grp_get_name(grp); - printf("%s\n", (char *)alpm_grp_get_name(grp)); - if(grp && level > 1) { - list_display(" ", alpm_grp_get_pkgs(grp)); + if(level > 1) { + for(k = alpm_grp_get_pkgs(grp); k; k = alpm_list_next(k)) { + printf("%s %s\n", grpname, + alpm_pkg_get_name(alpm_list_getdata(k))); + } + } else { + /* print grp names only, no package names */ + printf("%s\n", grpname); } } } @@ -395,7 +416,8 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } if(!db) { - fprintf(stderr, _("error: repository '%s' does not exist\n"), repo); + pm_fprintf(stderr, PM_LOG_ERROR, + _("repository '%s' does not exist\n"), repo); return(1); } @@ -410,7 +432,8 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } if(!foundpkg) { - fprintf(stderr, _("error: package '%s' was not found in repository '%s'\n"), pkgstr, repo); + pm_fprintf(stderr, PM_LOG_ERROR, + _("package '%s' was not found in repository '%s'\n"), pkgstr, repo); ret++; } } else { @@ -430,7 +453,8 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } } if(!foundpkg) { - fprintf(stderr, _("error: package '%s' was not found\n"), pkgstr); + pm_fprintf(stderr, PM_LOG_ERROR, + _("package '%s' was not found\n"), pkgstr); ret++; } } @@ -467,7 +491,8 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) } if(db == NULL) { - fprintf(stderr, _("error: repository \"%s\" was not found.\n"),repo); + pm_fprintf(stderr, PM_LOG_ERROR, + _("repository \"%s\" was not found.\n"),repo); alpm_list_free(ls); return(1); } @@ -499,74 +524,43 @@ 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 alpm_list_t *syncfirst() { + alpm_list_t *i, *res = NULL; + + for(i = config->syncfirst; i; i = alpm_list_next(i)) { + char *pkgname = alpm_list_getdata(i); + pmpkg_t *pkg = alpm_db_get_pkg(alpm_option_get_localdb(), pkgname); + if(pkg == NULL) { + continue; + } + + if(alpm_sync_newversion(pkg, alpm_option_get_syncdbs())) { + res = alpm_list_add(res, strdup(pkgname)); + } + } + + return(res); +} + +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) { - fprintf(stderr, _("error: %s\n"), alpm_strerrorlast()); + pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerrorlast()); retval = 1; goto cleanup; } - - if(!(alpm_trans_get_flags() & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) { - /* check if pacman itself is one of the packages to upgrade. - * this can prevent some of the "syntax error" problems users can have - * when sysupgrade'ing with an older version of pacman. - */ - pkgs = alpm_trans_get_pkgs(); - for(i = pkgs; i; i = alpm_list_next(i)) { - pmsyncpkg_t *sync = alpm_list_getdata(i); - pmpkg_t *spkg = alpm_sync_get_pkg(sync); - /* TODO pacman name should probably not be hardcoded. In addition, we - * have problems on an -Syu if pacman has to pull in deps, so recommend - * an '-S pacman' operation */ - 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) { - return(1); - } - if(sync_trans_init(0) == -1) { - return(1); - } - if(alpm_trans_addtarget("pacman") == -1) { - fprintf(stderr, _("error: pacman: %s\n"), alpm_strerrorlast()); - return(1); - } - break; - } - } - } - } } else { alpm_list_t *i; @@ -583,7 +577,7 @@ static int sync_trans(alpm_list_t *targets, int sync_only) continue; } if(pm_errno != PM_ERR_PKG_NOT_FOUND) { - fprintf(stderr, _("error: '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); retval = 1; goto cleanup; @@ -594,26 +588,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); } } @@ -622,7 +621,9 @@ static int sync_trans(alpm_list_t *targets, int sync_only) alpm_list_t *prov = NULL; for(j = sync_dbs; j; j = alpm_list_next(j)) { pmdb_t *db = alpm_list_getdata(j); - prov = alpm_list_join(prov, alpm_db_whatprovides(db, targ)); + alpm_list_t *dblist = alpm_db_getpkgcache(db); + alpm_list_t *satisfiers = alpm_find_pkg_satisfiers(dblist, targ); + prov = alpm_list_join(prov, satisfiers); } if(prov != NULL) { if(alpm_list_count(prov) == 1) { @@ -634,7 +635,8 @@ static int sync_trans(alpm_list_t *targets, int sync_only) targets = alpm_list_add(targets, strdup(pname)); } else { alpm_list_t *k; - fprintf(stderr, _("error: several packages provide %s, please specify one :\n"), targ); + pm_fprintf(stderr, PM_LOG_ERROR, + _("several packages provide %s, please specify one :\n"), targ); for(k = prov; k; k = alpm_list_next(k)) { pmpkg_t *pkg = alpm_list_getdata(k); printf("%s ", alpm_pkg_get_name(pkg)); @@ -645,7 +647,8 @@ static int sync_trans(alpm_list_t *targets, int sync_only) goto cleanup; } } else { - fprintf(stderr, _("error: '%s': not found in sync db\n"), targ); + pm_fprintf(stderr, PM_LOG_ERROR, + _("'%s': not found in sync db\n"), targ); retval = 1; goto cleanup; } @@ -656,7 +659,7 @@ static int sync_trans(alpm_list_t *targets, int sync_only) /* Step 2: "compute" the transaction based on targets and flags */ if(alpm_trans_prepare(&data) == -1) { - fprintf(stderr, _("error: failed to prepare transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { alpm_list_t *i; @@ -698,19 +701,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; @@ -719,7 +712,7 @@ static int sync_trans(alpm_list_t *targets, int sync_only) /* Step 3: actually perform the installation */ if(alpm_trans_commit(&data) == -1) { - fprintf(stderr, _("error: failed to commit transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { alpm_list_t *i; @@ -741,9 +734,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 +755,7 @@ cleanup: if(data) { FREELIST(data); } - if(sync_trans_release() == -1) { + if(trans_release() == -1) { retval = 1; } @@ -770,20 +765,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 +791,11 @@ 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)) { - /* 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(needs_transaction()) { - if(sync_trans(targets, sync_only) == 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); } } @@ -833,7 +820,43 @@ int pacman_sync(alpm_list_t *targets) return(sync_list(sync_dbs, targets)); } - return(0); + if(targets == NULL) { + if(config->op_s_upgrade) { + /* proceed */ + } else if(config->op_s_sync) { + return(0); + } else { + /* 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); + } + } + + alpm_list_t *targs = alpm_list_strdup(targets); + if(!(config->flags & (PM_TRANS_FLAG_DOWNLOADONLY | PM_TRANS_FLAG_PRINTURIS))) { + /* check for newer versions of packages to be upgraded first */ + alpm_list_t *packages = syncfirst(); + if(packages) { + printf(_(":: The following packages should be upgraded first :\n")); + list_display(" ", packages); + if(yesno(1, _(":: Do you want to cancel the current operation\n" + ":: and upgrade these packages now?"))) { + FREELIST(targs); + targs = packages; + config->flags = 0; + config->op_s_upgrade = 0; + } else { + FREELIST(packages); + } + printf("\n"); + } + } + + int ret = sync_trans(targs); + FREELIST(targs); + + return(ret); } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/add.c b/src/pacman/upgrade.c index fd40f005..c54b3ed7 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); } @@ -115,9 +73,9 @@ int pacman_add(alpm_list_t *targets) for(i = targets; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); if(alpm_trans_addtarget(targ) == -1) { - fprintf(stderr, _("error: '%s': %s\n"), + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); - add_cleanup(); + trans_release(); return(1); } } @@ -125,7 +83,7 @@ int pacman_add(alpm_list_t *targets) /* Step 2: "compute" the transaction based on targets and flags */ /* TODO: No, compute nothing. This is stupid. */ if(alpm_trans_prepare(&data) == -1) { - fprintf(stderr, _("error: failed to prepare transaction (%s)\n"), + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { case PM_ERR_UNSATISFIED_DEPS: @@ -171,7 +129,7 @@ int pacman_add(alpm_list_t *targets) default: break; } - add_cleanup(); + trans_release(); FREELIST(data); return(1); } @@ -179,12 +137,15 @@ 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(); + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), + alpm_strerrorlast()); + 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..e702886b 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) { + pm_fprintf(stderr, PM_LOG_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) { + pm_fprintf(stderr, PM_LOG_ERROR, _("failed to release transaction (%s)\n"), + alpm_strerrorlast()); + return(-1); + } + return(0); +} int needs_transaction() { @@ -94,33 +121,38 @@ int getcols() /* does the same thing as 'mkdir -p' */ int makepath(const char *path) { - char *orig, *str, *ptr; - char full[PATH_MAX+1] = ""; - mode_t oldmask; - - oldmask = umask(0000); + /* A bit of pointer hell here. Descriptions: + * orig - a copy of path so we can safely butcher it with strsep + * str - the current position in the path string (after the delimiter) + * ptr - the original position of str after calling strsep + * incr - incrementally generated path for use in stat/mkdir call + */ + char *orig, *str, *ptr, *incr; + mode_t oldmask = umask(0000); + int ret = 0; orig = strdup(path); + incr = calloc(strlen(orig) + 1, sizeof(char)); str = orig; while((ptr = strsep(&str, "/"))) { if(strlen(ptr)) { struct stat buf; - - /* TODO we should use strncat */ - strcat(full, "/"); - strcat(full, ptr); - if(stat(full, &buf)) { - if(mkdir(full, 0755)) { - free(orig); - umask(oldmask); - return(1); + /* we have another path component- append the newest component to + * existing string and create one more level of dir structure */ + strcat(incr, "/"); + strcat(incr, ptr); + if(stat(incr, &buf)) { + if(mkdir(incr, 0755)) { + ret = 1; + break; } } } } free(orig); + free(incr); umask(oldmask); - return(0); + return(ret); } /* does the same thing as 'rm -rf' */ @@ -234,6 +266,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; @@ -457,32 +493,29 @@ void display_targets(const alpm_list_t *syncpkgs, pmdb_t *db_local) const alpm_list_t *i, *j; alpm_list_t *targets = NULL, *to_remove = NULL; /* TODO these are some messy variable names */ - unsigned long isize = 0, rsize = 0, dispsize = 0, dlsize = 0; + off_t isize = 0, rsize = 0, dispsize = 0, dlsize = 0; double mbisize = 0.0, mbrsize = 0.0, mbdispsize = 0.0, mbdlsize = 0.0; for(i = syncpkgs; i; i = alpm_list_next(i)) { 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 +553,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; |