diff options
126 files changed, 3439 insertions, 2159 deletions
@@ -90,6 +90,17 @@ alpm_list_t *alpm_list_add(alpm_list_t *list, void *data) NOT if(!strcmp(a, b)) +8. Use spaces around almost all arithmetic, comparison and assignment + operators and after all ',;:' separators. + + foobar[2 * size + 1] = function(a, 6); + NOT + foobar[2*size+1]=function(a,6); + + for(a = 0; a < n && n > 0; a++,n--) {} + NOT + for(a=0;a<n&&n>0;a++,n--) {} + Other Concerns -------------- @@ -103,8 +114,6 @@ general pattern, including blank lines: [source,C] ------------------------------------------- -#include "config.h" - #include <standardheader.h> #include <another.h> #include <...> @@ -133,6 +142,8 @@ For pacman: #include "anythingelse.h" ------------------------------------------- +Never directly include config.h. This will always be added via Makefiles. + GDB and Valgrind Usage ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Makefile.am b/Makefile.am index 6b24a4aa..a024a2e6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,8 +1,10 @@ -SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util contrib +SUBDIRS = lib/libalpm src/util src/pacman scripts etc test/pacman test/util if WANT_DOC SUBDIRS += doc endif +DIST_SUBDIRS = $(SUBDIRS) contrib + ACLOCAL_AMFLAGS = -I m4 --install # Make sure we test and build manpages when doing distcheck @@ -389,7 +389,7 @@ API CHANGES BETWEEN 3.5 AND 4.0 - PM_ prefixes for enum values are now ALPM_ - pm prefixes for structs and enums are now alpm_ - alpm_initialize now has parameters: char *root, char *dbpath, - _alpm_errno_t *err and returns an alpm_handle_t struct. + alpm_errno_t *err and returns an alpm_handle_t struct. - alpm_release now takes an alpm_handle_t *. - alpm_db_register_sync() now requires a extra parameter of a alpm_siglevel_t. - alpm_pkg_load() now requires an extra parameter of an alpm_siglevel_t diff --git a/configure.ac b/configure.ac index 240d1c4c..18726cfb 100644 --- a/configure.ac +++ b/configure.ac @@ -57,7 +57,8 @@ AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) AC_CANONICAL_HOST -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([1.11]) +AM_SILENT_RULES([yes]) LIB_VERSION=`expr lib_current - lib_age`.lib_age.lib_revision LIB_VERSION_INFO="lib_current:lib_revision:lib_age" @@ -88,6 +89,12 @@ AC_ARG_WITH(buildscript, AS_HELP_STRING([--with-buildscript=name], [set the build script name used by makepkg]), [BUILDSCRIPT=$withval], [BUILDSCRIPT=PKGBUILD]) +# Help line for changing shell used to run install scriptlets +AC_ARG_WITH(scriptlet-shell, + AS_HELP_STRING([--with-scriptlet-shell=shell], + [set the full path to the shell used to run install scriptlets]), + [SCRIPTLET_SHELL=$withval], [SCRIPTLET_SHELL=/bin/sh]) + # Help line for using OpenSSL AC_ARG_WITH(openssl, AS_HELP_STRING([--with-openssl], [use OpenSSL crypto implementations instead of internal routines]), @@ -122,6 +129,10 @@ AC_ARG_ENABLE(git-version, [enable use of git version in version string if available]), [wantgitver=$enableval], [wantgitver=no]) +# Enable large file support if available (must be enabled before +# testing compilation against gpgme). +AC_SYS_LARGEFILE + # Checks for programs. AC_PROG_AWK AC_PROG_CC_C99 @@ -161,14 +172,42 @@ AM_CONDITIONAL([HAVE_LIBSSL], [test "x$with_openssl" = "xyes"]) # Check for gpgme AC_MSG_CHECKING(whether to link with libgpgme) AS_IF([test "x$with_gpgme" != "xno"], - [AC_MSG_RESULT(yes) - AC_CHECK_LIB([gpgme], [gpgme_check_version], , - [if test "x$with_gpgme" != "xcheck"; then - AC_MSG_FAILURE([--with-ggpme was given, but -lgpgme was not found]) - fi], - [-lgpgme]) - with_gpgme=$ac_cv_lib_gpgme_gpgme_check_version], - AC_MSG_RESULT(no)) + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + +require_gpgme=no +AS_IF([test "x$with_gpgme" != "xno"], + [AS_IF([test "x$with_gpgme" = "xyes"], + [require_gpgme=yes]) + AM_PATH_GPGME([1.3.0], + [LIBS_save="$LIBS" + CPPFLAGS_save="$CPPFLAGS" + CFLAGS_save="$CFLAGS" + + LIBS="$LIBS $GPGME_LIBS" + CPPFLAGS="$CPPFLAGS $GPGME_CPPFLAGS" + CFLAGS="$CFLAGS $GPGME_CFLAGS" + + AC_MSG_CHECKING([for sane gpgme]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include <gpgme.h>]], + [[const char *ver; +ver = gpgme_check_version("1.2.4");]])], + [AC_MSG_RESULT([yes]) + with_gpgme=yes + AC_DEFINE([HAVE_LIBGPGME], [1], [Define if gpgme should be used to provide GPG signature support.])], + [AC_MSG_RESULT([no]) + with_gpgme=no + LIBS="$LIBS_save" + CPPFLAGS="$CPPFLAGS_save" + CFLAGS="$CFLAGS_save"])], + [with_gpgme=no])]) +AS_IF([test "x$with_gpgme" != "xyes"], + [AS_IF([test "x$require_gpgme" = "xyes"], + [AC_MSG_FAILURE([--with-gpgme was given, but gpgme was not found])]) + with_gpgme=no]) + AM_CONDITIONAL([HAVE_LIBGPGME], [test "x$with_gpgme" = "xyes"]) # Checks for header files. @@ -203,6 +242,7 @@ AC_CHECK_FUNCS([dup2 getcwd geteuid getmntinfo gettimeofday memmove memset \ mkdir realpath regcomp rmdir setenv setlocale strcasecmp \ strchr strcspn strdup strerror strndup strrchr strsep strstr \ strtol swprintf tcflush wcwidth uname]) +AC_CHECK_MEMBERS([struct stat.st_blksize],,,[[#include <sys/stat.h>]]) # For the diskspace code FS_STATS_TYPE @@ -210,9 +250,6 @@ AC_CHECK_MEMBERS([struct statvfs.f_flag],,,[[#include <sys/statvfs.h>]]) AC_CHECK_MEMBERS([struct statfs.f_flags],,,[[#include <sys/param.h> #include <sys/mount.h>]]) -# Enable large file support if available -AC_SYS_LARGEFILE - # Check if we can use symbol visibility support in GCC GCC_VISIBILITY_CC # Check if we have -fgnu89-inline flag @@ -297,8 +334,6 @@ AC_MSG_CHECKING(for debug mode request) if test "x$debug" = "xyes" ; then AC_MSG_RESULT(yes) AC_DEFINE([PACMAN_DEBUG], , [Enable debug code]) - # Check for mcheck - AC_CHECK_HEADERS([mcheck.h]) # Check for -fstack-protector availability GCC_STACK_PROTECT_LIB GCC_STACK_PROTECT_CC @@ -330,6 +365,7 @@ AM_CONDITIONAL(USE_GIT_VERSION, test "x$usegitver" = "xyes") # Set root directory AC_SUBST(ROOTDIR) +AC_DEFINE_UNQUOTED([ROOTDIR], "$ROOTDIR", [The location of the root operating directory]) # Set package file extension AC_SUBST(PKGEXT) AC_DEFINE_UNQUOTED([PKGEXT], "$PKGEXT", [The file extension used by pacman packages]) @@ -339,6 +375,9 @@ AC_DEFINE_UNQUOTED([SRCEXT], "$SRCEXT", [The file extension used by pacman sourc # Set makepkg build script name AC_SUBST(BUILDSCRIPT) AC_DEFINE_UNQUOTED([BUILDSCRIPT], "$BUILDSCRIPT", [The build script name used by makepkg]) +# Set shell used by install scriptlets +AC_SUBST(SCRIPTLET_SHELL) +AC_DEFINE_UNQUOTED([SCRIPTLET_SHELL], "$SCRIPTLET_SHELL", [The full path of the shell used to run install scriptlets]) # Configuration files AC_CONFIG_FILES([ diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 0ff1d9db..eca39e75 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -1,3 +1,9 @@ +# enforce that all scripts have a --help and --version option +AUTOMAKE_OPTIONS = std-options + +bin_SCRIPTS = \ + $(OURSCRIPTS) + OURSCRIPTS = \ bacman \ paccache \ @@ -30,29 +36,44 @@ EXTRA_DIST = \ # Files that should be removed, but which Automake does not know. MOSTLYCLEANFILES = $(OURSCRIPTS) $(OURFILES) *.tmp +if USE_GIT_VERSION +GIT_VERSION := $(shell sh -c 'git describe --abbrev=4 --dirty | sed s/^v//') +REAL_PACKAGE_VERSION = $(GIT_VERSION) +else +REAL_PACKAGE_VERSION = $(PACKAGE_VERSION) +endif + edit = sed \ -e 's|@sysconfdir[@]|$(sysconfdir)|g' \ -e 's|@localstatedir[@]|$(localstatedir)|g' \ + -e 's|@PACKAGE_VERSION[@]|$(REAL_PACKAGE_VERSION)|g' \ -e 's|@SIZECMD[@]|$(SIZECMD)|g' \ -e '1s|!/bin/bash|!$(BASH_SHELL)|g' $(OURSCRIPTS): Makefile - @echo ' ' GEN $@; - @$(RM) $@ $@.tmp - @$(edit) $(srcdir)/$@.in >$@.tmp - @chmod +x $@.tmp - @chmod a-w $@.tmp - @mv $@.tmp $@ + $(AM_V_at)$(RM) $@ $@.tmp + $(AM_V_GEN)$(edit) $(srcdir)/$@.in >$@.tmp + $(AM_V_at)chmod +x,a-w $@.tmp + $(AM_V_at)mv $@.tmp $@ $(OURFILES): Makefile - @echo ' ' GEN $@; - @$(RM) $@ $@.tmp - @$(edit) $(srcdir)/$@.in >$@.tmp - @chmod a-w $@.tmp - @mv $@.tmp $@ + $(AM_V_at)$(RM) $@ $@.tmp + $(AM_V_GEN)$(edit) $(srcdir)/$@.in >$@.tmp + $(AM_V_at)chmod a-w $@.tmp + $(AM_V_at)mv $@.tmp $@ all-am: $(OURSCRIPTS) $(OURFILES) +install-data-local: + $(MKDIR_P) $(DESTDIR)$(sysconfdir)/bash_completion.d/ + $(INSTALL_DATA) bash_completion $(DESTDIR)$(sysconfdir)/bash_completion.d/pacman + $(MKDIR_P) $(DESTDIR)$(datarootdir)/zsh/site-functions/ + $(INSTALL_DATA) zsh_completion $(DESTDIR)$(datarootdir)/zsh/site-functions/_pacman + +uninstall-local: + $(RM) $(DESTDIR)$(sysconfdir)/bash_completion.d/pacman + $(RM) $(DESTDIR)$(datarootdir)/zsh/site-functions/_pacman + bacman: $(srcdir)/bacman.in bash_completion: $(srcdir)/bash_completion.in paccache: $(srcdir)/paccache.in diff --git a/contrib/bacman.in b/contrib/bacman.in index c55d7161..93623565 100755 --- a/contrib/bacman.in +++ b/contrib/bacman.in @@ -23,16 +23,21 @@ shopt -s extglob shopt -s nullglob -readonly progname="bacman" -readonly progver="0.2.1" +declare -r myname='bacman' +declare -r myver='@PACKAGE_VERSION@' # # User Friendliness # usage() { echo "This program recreates a package using pacman's db and system files" - echo "Usage: $progname <installed package name>" - echo "Example: $progname kernel26" + echo "Usage: $myname <installed package name>" + echo "Example: $myname kernel26" +} + +version() { + printf "%s %s\n" "$myname" "$myver" + echo 'Copyright (C) 2008 locci <carlocci_at_gmail_dot_com>' } if (( $# != 1 )); then @@ -40,14 +45,11 @@ if (( $# != 1 )); then exit 1 fi -if [[ $1 == "--help" || $1 == "-h" ]]; then +if [[ $1 = -@(h|-help) ]]; then usage exit 0 -fi - -if [[ $1 == "--version" || $1 == "-v" ]]; then - echo "$progname version $progver" - echo "Copyright (C) 2008 locci" +elif [[ $1 = -@(V|-version) ]]; then + version exit 0 fi @@ -61,7 +63,7 @@ if (( EUID )); then /usr/bin/fakeroot -u -- "$0" "$@" exit $? else - echo "WARNING: installing fakeroot or running ${progname} as root is required to" + echo "WARNING: installing fakeroot or running $myname as root is required to" echo " preserve the ownership permissions of files in some packages" echo "" fi @@ -151,7 +153,7 @@ while read i; do 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" + echo " you will need to run $myname as root" rm -rf "$work_dir" exit 1 fi @@ -177,7 +179,7 @@ pkg_size=$(du -sk | awk '{print $1 * 1024}') # TODO adopt makepkg's write_pkginfo() into this or scripts/library # echo Generating .PKGINFO metadata... -echo "# Generated by $progname $progver" > .PKGINFO +echo "# Generated by $myname $myver" > .PKGINFO if [[ $INFAKEROOT == "1" ]]; then echo "# Using $(fakeroot -v)" >> .PKGINFO fi diff --git a/contrib/bash_completion.in b/contrib/bash_completion.in index 8983c92b..95a27702 100644 --- a/contrib/bash_completion.in +++ b/contrib/bash_completion.in @@ -31,12 +31,14 @@ _pacman_key() { local cur opts prev COMPREPLY=() _get_comp_words_by_ref cur prev - if [[ $cur = -* && + opts=('add delete export finger help list-keys recv-keys updatedb verify + version config edit-key gpgdir import import-trustdb init keyserver + list-sigs lsign-key populate refresh-keys' + 'a d e f h l r u v V') + if [[ $prev = 'pacman-key' ]]; then + _arch_ptr2comp opts + elif [[ $cur = -* && $prev != -@(a|-add|c|-config|g|-gpgdir|h|-help|import?(-trustdb)) ]]; then - opts=('add delete export finger help list-keys recv-keys updatedb verify version - config edit-key gpgdir import import-trustdb init keyserver list-sigs - lsign-key populate refresh-keys' - 'a d e f h l r u v V') _arch_ptr2comp opts fi true @@ -76,8 +78,8 @@ _pacman() { remove=('cascade dbonly nodeps nosave print recursive unneeded' 'c n p s u') sync=('asdeps asexplicit clean dbonly downloadonly force groups ignore ignoregroup info list needed nodeps print refresh recursive search sysupgrade' - 'c f g i l p s u w y') - upgrade=('asdeps asexplicit force needed nodeps print recursive' 'f p') + 'c g i l p s u w y') + upgrade=('asdeps asexplicit force needed nodeps print recursive' 'p') common=('arch cachedir config dbpath debug help logfile noconfirm noprogressbar noscriptlet quiet root verbose' 'b d h q r v') core=('database help query remove sync upgrade version' 'D Q R S U V h') @@ -111,18 +113,11 @@ _pacman() { true } -if [[ $(type -t compopt) = "builtin" ]]; then - _pacman_file() { - compopt -o filenames; _filedir 'pkg.tar*' - } - complete -F _pacman -o default pacman -else - _pacman_file() { - _filedir 'pkg.tar*' - } - complete -F _pacman -o filenames -o default pacman -fi +_pacman_file() { + compopt -o filenames; _filedir 'pkg.tar*' +} +complete -F _pacman -o default pacman complete -F _makepkg -o default makepkg complete -F _pacman_key -o default pacman-key diff --git a/contrib/paccache.in b/contrib/paccache.in index a9e5bfbc..da65f476 100755 --- a/contrib/paccache.in +++ b/contrib/paccache.in @@ -20,6 +20,9 @@ shopt -s extglob +declare -r myname='paccache' +declare -r myver='@PACKAGE_VERSION@' + declare -a candidates=() cmdopts=() whitelist=() blacklist=() declare -i delete=0 dryrun=0 filecount=0 move=0 needsroot=0 totalsaved=0 verbose=0 declare cachedir=@localstatedir@/cache/pacman/pkg delim=$'\n' keep=3 movedir= scanarch= @@ -174,9 +177,9 @@ summarize() { usage() { cat <<EOF -usage: ${0##*/} <operation> [options] [targets...] +usage: $myname <operation> [options] [targets...] -${0##*/} is a flexible pacman cache cleaning utility, which has numerous +$myname is a flexible pacman cache cleaning utility, which has numerous options to help control how much, and what, is deleted from any directory containing pacman package tarballs. @@ -200,19 +203,32 @@ containing pacman package tarballs. EOF } +version() { + printf "%s %s\n" "$myname" "$myver" + echo 'Copyright (C) 2011 Dave Reisner <dreisner@archlinux.org>' +} + if (( ! UID )); then error "Do not run this script as root. You will be prompted for privilege escalation." exit 42 fi -while getopts ':a:c:dfhi:k:m:rsuvz' opt; do +# TODO: remove this workaround and use a sane command line parser (like the +# parse_options library from scripts/) here +if [[ $1 = -@(h|-help) ]]; then + usage + exit 0 +elif [[ $1 = -@(V|-version) ]]; then + version + exit 0 +fi + +while getopts ':a:c:dfi:k:m:rsuvz' opt; do case $opt in a) scanarch=$OPTARG ;; c) cachedir=$OPTARG ;; d) dryrun=1 ;; f) cmdopts=(-f) ;; - h) usage - exit 0 ;; i) if [[ $OPTARG = '-' ]]; then [[ ! -t 0 ]] && IFS=$'\n' read -r -d '' -a ign else diff --git a/contrib/pacdiff.in b/contrib/pacdiff.in index 3f26f381..bfafda26 100755 --- a/contrib/pacdiff.in +++ b/contrib/pacdiff.in @@ -17,17 +17,25 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # +declare -r myname='pacdiff' +declare -r myver='@PACKAGE_VERSION@' + diffprog=${DIFFPROG:-vimdiff} diffsearchpath=${DIFFSEARCHPATH:-/etc} locate=0 usage() { - echo "pacdiff : a simple pacnew/pacorig/pacsave updater" - echo "Usage : pacdiff [-l]" - echo " -l/--locate makes pacdiff use locate rather than find" + echo "$myname : a simple pacnew/pacorig/pacsave updater" + echo "Usage : $myname [-l]" + echo " -l/--locate makes $myname use locate rather than find" echo " DIFFPROG variable allows to override the default vimdiff" echo " DIFFSEARCHPATH allows to override the default /etc path" - echo "Example : DIFFPROG=meld DIFFSEARCHPATH=\"/boot /etc /usr\" pacdiff" + echo "Example : DIFFPROG=meld DIFFSEARCHPATH=\"/boot /etc /usr\" $myname" +} + +version() { + printf "%s %s\n" "$myname" "$myver" + echo 'Copyright (C) 2007 Aaron Griffin <aaronmgriffin@gmail.com>' } cmd() { @@ -42,8 +50,12 @@ if [ $# -gt 0 ]; then case $1 in -l|--locate) locate=1;; - *) + -V|--version) + version; exit 0;; + -h|--help) usage; exit 0;; + *) + usage; exit 1;; esac fi diff --git a/contrib/paclist.in b/contrib/paclist.in index 06b06f2c..7883e21b 100755 --- a/contrib/paclist.in +++ b/contrib/paclist.in @@ -17,6 +17,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +declare -r myname='paclist' +declare -r myver='@PACKAGE_VERSION@' + export TEXTDOMAIN='pacman' export TEXTDOMAINDIR='/usr/share/locale' @@ -27,13 +30,31 @@ if ! type gettext &>/dev/null; then } fi -if [[ -z $1 || $1 = -@(h|-help) ]]; then - printf '%s - List all packages installed from a given repo\n' "${0##*/}" - printf 'Usage: %s <repo>\n' "${0##*/}" - printf 'Example: %s testing\n' "${0##*/}" +usage() { + printf '%s - List all packages installed from a given repo\n' "$myname" + printf 'Usage: %s <repo>\n' "$myname" + printf 'Example: %s testing\n' "$myname" +} + +version() { + printf "%s %s\n" "$myname" "$myver" + echo 'Copyright (C) 2008 Dan McGee <dpmcgee@gmail.com>' + echo 'Copyright (C) 2011 Dave Reisner <dreisner@archlinux.org>' +} + +if [[ -z $1 ]]; then + usage exit 1 fi +if [[ $1 = -@(h|-help) ]]; then + usage + exit 0 +elif [[ $1 = -@(V|-version) ]]; then + version + exit 0 +fi + printf -v installed '[%s]' "$(gettext installed)" pacman -Sl $1 | awk -v i="$installed" '$NF == i { print $2,$3 }' diff --git a/contrib/paclog-pkglist.in b/contrib/paclog-pkglist.in index 27dfd302..222bbc4c 100755 --- a/contrib/paclog-pkglist.in +++ b/contrib/paclog-pkglist.in @@ -17,15 +17,30 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +declare -r myname='paclog-pkglist' +declare -r myver='@PACKAGE_VERSION@' + export TEXTDOMAIN='pacman' export TEXTDOMAINDIR='/usr/share/locale' declare logfile=${1:-@localstatedir@/log/pacman.log} +usage() { + printf 'usage: %s [pacman log]\n' "$myname" + printf 'example: %s @localstatedir@/log/pacman.log\n' "$myname" + printf '\ndefaults to: @localstatedir@/log/pacman.log\n' +} + +version() { + printf "%s %s\n" "$myname" "$myver" + echo 'Copyright (C) 2011 Dave Reisner <dave@archlinux.org>' +} + if [[ $1 ]]; then if [[ $1 = -@(h|-help) ]]; then - printf 'usage: %s [pacman log]\n' "${0##*/}" - printf 'example: %s @localstatedir@/log/pacman.log\n' "${0##*/}" - printf '\ndefaults to: @localstatedir@/log/pacman.log\n' + usage + exit 0 + elif [[ $1 = -@(V|-version) ]]; then + version exit 0 elif [[ ! -e $logfile ]]; then printf $"target not found: %s\n" "$1" diff --git a/contrib/pacscripts.in b/contrib/pacscripts.in index 37d3feae..84687145 100755 --- a/contrib/pacscripts.in +++ b/contrib/pacscripts.in @@ -24,8 +24,8 @@ set -o nounset set -o errexit -progname=$(basename $0) -progver="0.4" +declare -r myname='pacscripts' +declare -r myver='@PACKAGE_VERSION@' conf="@sysconfdir@/pacman.conf" @@ -47,14 +47,20 @@ error() { usage() { echo "This program prints out the {pre,post}_{install,remove,upgrade} scripts" echo "of a given package." - echo "Usage: $progname pkgname|pkgfile" + echo "Usage: $myname pkgname|pkgfile" echo echo " OPTIONS:" echo " -h, --help Print this help message" echo " -v, --version Print program name and version" echo - echo "Example: $progname gconf-editor" - echo "Example: $progname gconf-editor-2.24.1-1-x86_64.pkg.tar.gz" + echo "Example: $myname gconf-editor" + echo "Example: $myname gconf-editor-2.24.1-1-x86_64.pkg.tar.gz" +} + +version() { + printf "%s %s\n" "$myname" "$myver" + echo 'Copyright (c) 2009 Giulio "giulivo" Fidente <giulivo.navigante@gmail.com>' + echo 'Copyright (c) 2009 Xavier Chantry <shiningxc@gmail.com>' } spacman() { @@ -127,6 +133,6 @@ fi case "$1" in --help|-h) usage; exit 0 ;; - --version|-v) echo "$progname version $progver"; exit 0 ;; + --version|-V) version; exit 0 ;; *) print_scriptlet $1 ;; esac diff --git a/contrib/pacsearch.in b/contrib/pacsearch.in index db9d6ad1..b1db8abe 100755 --- a/contrib/pacsearch.in +++ b/contrib/pacsearch.in @@ -24,22 +24,32 @@ use strict; use warnings; -my $progname = "pacsearch"; -my $version = "2.0"; +my $myname = 'pacsearch'; +my $myver = '@PACKAGE_VERSION@'; + +sub usage { + print "$myname - Add color and install information to a pacman -Ss search\n"; + print "Usage: $myname <pattern>\n"; + print "Example: $myname ^gnome\n"; +} + +sub version { + printf "%s %s\n", $myname, $myver; + print "Copyright (C) 2008-2011 Dan McGee <dan\@archlinux.org>\n\n"; + print "Based off original shell script version:\n"; + print "Copyright (C) 2006-2007 Dan McGee <dan\@archlinux.org>\n"; +} 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"; + usage; if ($#ARGV lt 0) { exit 1; } exit 0; } -if ($ARGV[0] eq "--version" || $ARGV[0] eq "-v") { - print "$progname version $version\n"; - print "Copyright (C) 2006-2011 Dan McGee\n"; +if ($ARGV[0] eq "--version" || $ARGV[0] eq "-V") { + version; exit 0; } diff --git a/contrib/pacsysclean.in b/contrib/pacsysclean.in index a4accd56..162530ef 100755 --- a/contrib/pacsysclean.in +++ b/contrib/pacsysclean.in @@ -2,23 +2,32 @@ # pacsysclean - Sort installed packages by increasing installed size. Useful for system clean-up. +declare -r myname='pacsysclean' +declare -r myver='@PACKAGE_VERSION@' + PACMAN_OPTS= usage() { - echo "pacsysclean - Sort installed packages by increasing installed size." + echo "$myname - Sort installed packages by increasing installed size." echo - echo "Usage: pacsysclean [options]" + echo "Usage: $myname [options]" echo echo "Options:" echo " -o <options> Specify custom pacman query options (e.g., dt)" echo " -h, --help Show this help message and exit" } +version() { + printf "%s %s\n" "$myname" "$myver" + echo 'Copyright (C) 2011 Eric BĂ©langer <snowmaniscool@gmail.com>' +} + if [ -n "$1" ]; then case "$1" in -o) PACMAN_OPTS="${2}" ;; -h|--help) usage; exit 0 ;; + -V|--version) version; exit 0 ;; *) usage; exit 1 ;; esac fi diff --git a/contrib/zsh_completion.in b/contrib/zsh_completion.in index 2cfc946c..b30e9600 100644 --- a/contrib/zsh_completion.in +++ b/contrib/zsh_completion.in @@ -32,8 +32,8 @@ _pacman_opts_common=( # options for passing to _arguments: options for --upgrade commands _pacman_opts_pkgfile=( '-d[Skip dependency checks]' - '-f[Overwrite conflicting files]' '--dbonly[Only remove database entry, do not remove files]' + '--force[Overwrite conflicting files]' '--needed[Do not reinstall up to date packages]' '--recursive[Reinstall all dependencies of target packages]' '*:package file:_files -g "*.pkg.tar*(.)"' @@ -85,7 +85,6 @@ _pacman_opts_sync_actions=( # options for passing to _arguments: options for --sync command _pacman_opts_sync_modifiers=( '-d[Skip dependency checks]' - '-f[Overwrite conflicting files]' '-i[View package information]' '-l[List all packages in a repository]' '-p[Print download URIs for each package to be installed]' @@ -98,6 +97,7 @@ _pacman_opts_sync_modifiers=( _pacman_completions_all_groups' '--asdeps[Install packages as non-explicitly installed]' '--asexplicit[Install packages as explicitly installed]' + '--force[Overwrite conflicting files]' ) # handles --help subcommand diff --git a/doc/Makefile.am b/doc/Makefile.am index 4c1700b9..a2018c71 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -90,8 +90,10 @@ endif html: $(HTML_DOCS) -website: html - bsdtar czf website.tar.gz $(HTML_DOCS) \ +website: website.tar.gz + +website.tar.gz: html + $(AM_V_GEN)bsdtar czf $@ $(HTML_DOCS) \ asciidoc-override.css \ -C /etc/asciidoc/stylesheets/ \ asciidoc.css \ @@ -119,15 +121,15 @@ A2X_OPTS = \ # These rules are due to the includes and files of the asciidoc text $(ASCIIDOC_MANS): asciidoc.conf footer.txt Makefile.am - a2x $(A2X_OPTS) --asciidoc-opts="$(ASCIIDOC_OPTS) --out-file=./$@.xml" $(srcdir)/$@.txt + $(AM_V_GEN)a2x $(A2X_OPTS) --asciidoc-opts="$(ASCIIDOC_OPTS) --out-file=./$@.xml" $(srcdir)/$@.txt %.html: %.txt - asciidoc $(ASCIIDOC_OPTS) $*.txt - dos2unix $@ + $(AM_V_GEN)asciidoc $(ASCIIDOC_OPTS) -o - $*.txt | \ + sed -e 's/\r$$//' > $@ HACKING.html: ../HACKING - asciidoc $(ASCIIDOC_OPTS) -o $@ ../HACKING - dos2unix $@ + $(AM_V_GEN)asciidoc $(ASCIIDOC_OPTS) -o - ../HACKING | \ + sed -e 's/\r$$//' > $@ # Customizations for certain HTML docs $(HTML_MANPAGES): asciidoc.conf footer.txt Makefile.am diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index fad93e5c..a21c1dff 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -120,9 +120,10 @@ of the corresponding source file. *md5sums (array)*:: This array contains an MD5 hash for every source file specified in the 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. + file integrity during subsequent builds. If 'SKIP' is put in the array + in place of a normal hash, the integrity check for that source file will + be skipped. To easily generate md5sums, run ``makepkg -g >> PKGBUILD''. + If desired, move the md5sums line to an appropriate location. *sha1sums, sha256sums, sha384sums, sha512sums (arrays)*:: Alternative integrity checks that makepkg supports; these all behave diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt index f693a5a8..df41e187 100644 --- a/doc/makepkg.8.txt +++ b/doc/makepkg.8.txt @@ -207,6 +207,10 @@ Environment Variables Folder where the downloaded sources will be stored. Overrides the corresponding value defined in linkman:makepkg.conf[5]. +**PACKAGER=**"John Doe <john@doe.com>":: + String to identify the creator of the resulting package. Overrides + the corresponding value defined in linkman:makepkg.conf[5]. + **BUILDDIR=**"/path/to/folder":: Folder where the package will be built. Overrides the corresponding value defined in linkman:makepkg.conf[5]. diff --git a/doc/makepkg.conf.5.txt b/doc/makepkg.conf.5.txt index db1e6d53..5970946d 100644 --- a/doc/makepkg.conf.5.txt +++ b/doc/makepkg.conf.5.txt @@ -213,6 +213,10 @@ Options This value is used when querying a package to see who was the builder. It is recommended you change this to your name and email address. +**COMPRESSGZ=**"(gzip -c -f -n)", **COMPRESSBZ2=**"(bzip2 -c -f)", **COMPRESSXZ=**"(xz -c -z -)", **COMPRESSZ=**"(compress -c -f)":: + Sets the command and options used when compressing compiled or source + packages in the named format. + **PKGEXT=**".pkg.tar.gz", **SRCEXT=**".src.tar.gz":: Sets the compression used when making compiled or source packages. The current valid suffixes are `.tar`, `.tar.gz`, `.tar.bz2`, `.tar.xz`, and diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 1ec5e7c3..275cf965 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -201,7 +201,7 @@ Transaction Options (apply to '-S', '-R' and '-U') Upgrade Options (apply to '-S' and '-U')[[UO]] -------------------------------------------- -*-f, \--force*:: +*\--force*:: Bypass file conflict checks and overwrite conflicting files. If the package that is about to be installed contains files that are already installed, this option will cause all those files to be overwritten. diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index e793e78b..39132925 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -86,11 +86,12 @@ Options *HoldPkg =* package ...:: If a user tries to '\--remove' a package that's listed in `HoldPkg`, - pacman will ask for confirmation before proceeding. + pacman will ask for confirmation before proceeding. Shell-style glob + patterns are allowed. *IgnorePkg =* package ...:: Instructs pacman to ignore any upgrades for this package when performing - a '\--sysupgrade'. + a '\--sysupgrade'. Shell-style glob patterns are allowed. *SyncFirst =* package ...:: Instructs pacman to check for newer version of these packages before any @@ -103,7 +104,8 @@ Options *IgnoreGroup =* group ...:: Instructs pacman to ignore any upgrades for all packages in this - group when performing a '\--sysupgrade'. + group when performing a '\--sysupgrade'. Shell-style glob patterns are + allowed. *Include =* path:: Include another config file. This file can include repositories or @@ -134,7 +136,8 @@ Options a package install/upgrade, and the new files will be installed with a '.pacnew' extension. These files refer to files in the package archive, so do not include the - leading slash (the RootDir) when specifying them. + leading slash (the RootDir) when specifying them. Shell-style glob patterns + are allowed. *NoExtract =* file ...:: All files listed with a `NoExtract` directive will never be extracted from @@ -143,7 +146,8 @@ Options 'index.php', then you would not want the 'index.html' file to be extracted from the 'apache' package. These files refer to files in the package archive, so do not include the - leading slash (the RootDir) when specifying them. + leading slash (the RootDir) when specifying them. Shell-style glob patterns + are allowed. *CleanMethod =* KeepInstalled &| KeepCurrent:: If set to `KeepInstalled` (the default), the '-Sc' operation will clean @@ -164,9 +168,13 @@ Options Log action messages through syslog(). This will insert log entries into +{localstatedir}/log/messages+ or equivalent. -*UseDelta*:: - Download delta files instead of complete packages if possible. Requires - the xdelta3 program to be installed. +*UseDelta* [= ratio]:: + Download delta files instead of complete packages if possible. Requires + the `xdelta3` program to be installed. If a ratio is specified (e.g., + `0.5`), then it is used as a cutoff for determining whether to use deltas. + Allowed values are between `0.0` and `2.0`; sensible values are between + `0.2` and `0.9`. Using a value above `1.0` is not recommended. The + default is `0.7` if left unspecified. *TotalDownload*:: When downloading, display the amount downloaded, download rate, ETA, diff --git a/etc/Makefile.am b/etc/Makefile.am index d504d7fc..58a80bdc 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -22,10 +22,9 @@ edit = sed \ -e 's|@ROOTDIR[@]|$(ROOTDIR)|g' $(dist_sysconf_DATA): Makefile - @echo ' ' GEN $@; - @$(RM) $@ $@.tmp - @$(edit) `test -f ./$@.in || echo $(srcdir)/`$@.in >$@.tmp - @mv $@.tmp $@ + $(AM_V_at)$(RM) $@ $@.tmp + $(AM_V_GEN)$(edit) `test -f ./$@.in || echo $(srcdir)/`$@.in >$@.tmp + $(AM_V_at)mv $@.tmp $@ makepkg.conf: $(srcdir)/makepkg.conf.in pacman.conf: $(srcdir)/pacman.conf.in diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index e9152c8b..d8117a37 100644 --- a/etc/makepkg.conf.in +++ b/etc/makepkg.conf.in @@ -9,8 +9,8 @@ #-- The download utilities that makepkg should use to acquire sources # Format: 'protocol::agent' DLAGENTS=('ftp::/usr/bin/curl -fC - --ftp-pasv --retry 3 --retry-delay 3 -o %o %u' - 'http::/usr/bin/curl -fLC - --retry 3 --retry-delay 3 -o %o %u' - 'https::/usr/bin/curl -fLC - --retry 3 --retry-delay 3 -o %o %u' + 'http::/usr/bin/curl -b "" -fLC - --retry 3 --retry-delay 3 -o %o %u' + 'https::/usr/bin/curl -b "" -fLC - --retry 3 --retry-delay 3 -o %o %u' 'rsync::/usr/bin/rsync --no-motd -z %u %o' 'scp::/usr/bin/scp -C %u %o') @@ -107,6 +107,16 @@ PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) #GPGKEY="" ######################################################################### +# COMPRESSION DEFAULTS +######################################################################### +# +COMPRESSGZ=(gzip -c -f -n) +COMPRESSBZ2=(bzip2 -c -f) +COMPRESSXZ=(xz -c -z -) +COMPRESSZ=(compress -c -f) + + +######################################################################### # EXTENSION DEFAULTS ######################################################################### # diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in index 932140f4..7f9db1b5 100644 --- a/etc/pacman.conf.in +++ b/etc/pacman.conf.in @@ -20,6 +20,7 @@ SyncFirst = pacman #XferCommand = /usr/bin/curl -C - -f %u > %o #XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u #CleanMethod = KeepInstalled +#UseDelta = 0.7 Architecture = auto # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup @@ -31,7 +32,6 @@ Architecture = auto # Misc options #UseSyslog -#UseDelta #TotalDownload CheckSpace #VerbosePkgLists diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index 99f9c1b7..61dcb877 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -7,6 +7,9 @@ include_HEADERS = alpm_list.h alpm.h DEFS = -DLOCALEDIR=\"@localedir@\" @DEFS@ +AM_CPPFLAGS = \ + -imacros $(top_builddir)/config.h + AM_CFLAGS = -pedantic -D_GNU_SOURCE if ENABLE_VISIBILITY_CC diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 6c2f0cb6..b0077665 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -1,7 +1,7 @@ /* * add.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,19 +18,15 @@ * 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 <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> -#include <inttypes.h> /* int64_t */ -#include <stdint.h> /* intmax_t */ +#include <stdint.h> /* int64_t */ /* libarchive */ #include <archive.h> @@ -132,6 +128,18 @@ static int perform_extraction(alpm_handle_t *handle, struct archive *archive, return 0; } +static int try_rename(alpm_handle_t *handle, const char *src, const char *dest) +{ + if(rename(src, dest)) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + src, dest, strerror(errno)); + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", + src, dest, strerror(errno)); + return 1; + } + return 0; +} + static int extract_single_file(alpm_handle_t *handle, struct archive *archive, struct archive_entry *entry, alpm_pkg_t *newpkg, alpm_pkg_t *oldpkg) { @@ -146,8 +154,6 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, 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", @@ -170,7 +176,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, } /* if a file is in NoExtract then we never extract it */ - if(alpm_list_find_str(handle->noextract, entryname)) { + if(alpm_list_find(handle->noextract, entryname, _alpm_fnmatch)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract, skipping extraction\n", entryname); alpm_logaction(handle, "note: %s is in NoExtract, skipping extraction\n", @@ -250,7 +256,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, } else if(S_ISREG(entrymode)) { /* case 4,7: */ /* if file is in NoUpgrade, don't touch it */ - if(alpm_list_find_str(handle->noupgrade, entryname)) { + if(alpm_list_find(handle->noupgrade, entryname, _alpm_fnmatch)) { notouch = 1; } else { alpm_backup_t *backup; @@ -282,17 +288,18 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, STRDUP(entryname_orig, entryname, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); if(needbackup) { - char checkfile[PATH_MAX]; + char *checkfile; char *hash_local = NULL, *hash_pkg = NULL; - int ret; + size_t len; - snprintf(checkfile, PATH_MAX, "%s.paccheck", filename); + len = strlen(filename) + 10; + MALLOC(checkfile, len, + errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup); + snprintf(checkfile, len, "%s.paccheck", filename); - ret = perform_extraction(handle, archive, entry, checkfile, entryname_orig); - if(ret == 1) { - /* error */ - FREE(entryname_orig); - return 1; + if(perform_extraction(handle, archive, entry, checkfile, entryname_orig)) { + errors++; + goto needbackup_cleanup; } hash_local = alpm_compute_md5sum(filename); @@ -320,29 +327,26 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) != 0) { /* looks like we have a local file that has a different hash as the * file in the package, move it to a .pacorig */ - char newpath[PATH_MAX]; - snprintf(newpath, PATH_MAX, "%s.pacorig", filename); + char *newpath; + size_t newlen = strlen(filename) + 9; + MALLOC(newpath, newlen, + errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup); + snprintf(newpath, newlen, "%s.pacorig", filename); /* move the existing file to the "pacorig" */ - if(rename(filename, newpath)) { - _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), - filename, newpath, strerror(errno)); - alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", - filename, newpath, strerror(errno)); + if(try_rename(handle, filename, newpath)) { + errors++; errors++; } else { /* rename the file we extracted to the real name */ - if(rename(checkfile, filename)) { - _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), - checkfile, filename, strerror(errno)); - alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", - checkfile, filename, strerror(errno)); + if(try_rename(handle, checkfile, filename)) { errors++; } else { _alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath); alpm_logaction(handle, "warning: %s saved as %s\n", filename, newpath); } } + free(newpath); } else { /* local file is identical to pkg one, so just remove pkg one */ unlink(checkfile); @@ -356,11 +360,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, _alpm_log(handle, ALPM_LOG_DEBUG, "action: installing new file: %s\n", entryname_orig); - if(rename(checkfile, filename)) { - _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), - checkfile, filename, strerror(errno)); - alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", - checkfile, filename, strerror(errno)); + if(try_rename(handle, checkfile, filename)) { errors++; } } else { @@ -382,29 +382,30 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, _alpm_log(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n"); unlink(checkfile); } else { - char newpath[PATH_MAX]; + char *newpath; + size_t newlen = strlen(filename) + 8; _alpm_log(handle, ALPM_LOG_DEBUG, "action: keeping current file and installing" " new one with .pacnew ending\n"); - snprintf(newpath, PATH_MAX, "%s.pacnew", filename); - if(rename(checkfile, newpath)) { - _alpm_log(handle, ALPM_LOG_ERROR, _("could not install %s as %s (%s)\n"), - filename, newpath, strerror(errno)); - alpm_logaction(handle, "error: could not install %s as %s (%s)\n", - filename, newpath, strerror(errno)); + MALLOC(newpath, newlen, + errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup); + snprintf(newpath, newlen, "%s.pacnew", filename); + if(try_rename(handle, checkfile, newpath)) { + errors++; } else { _alpm_log(handle, ALPM_LOG_WARNING, _("%s installed as %s\n"), filename, newpath); alpm_logaction(handle, "warning: %s installed as %s\n", filename, newpath); } + free(newpath); } } - FREE(hash_local); - FREE(hash_pkg); +needbackup_cleanup: + free(checkfile); + free(hash_local); + free(hash_pkg); } else { - int ret; - /* we didn't need a backup */ if(notouch) { /* change the path to a .pacnew extension */ @@ -423,11 +424,11 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, unlink(filename); } - ret = perform_extraction(handle, archive, entry, filename, entryname_orig); - if(ret == 1) { + if(perform_extraction(handle, archive, entry, filename, entryname_orig)) { /* error */ - FREE(entryname_orig); - return 1; + free(entryname_orig); + errors++; + return errors; } /* calculate an hash if this is in newpkg's backup */ @@ -444,7 +445,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, backup->hash = newhash; } } - FREE(entryname_orig); + free(entryname_orig); return errors; } @@ -521,31 +522,20 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) { struct archive *archive; struct archive_entry *entry; - int cwdfd; + struct stat buf; + int fd, cwdfd; _alpm_log(handle, ALPM_LOG_DEBUG, "extracting files\n"); - if((archive = archive_read_new()) == NULL) { - handle->pm_errno = ALPM_ERR_LIBARCHIVE; - ret = -1; - goto cleanup; - } - - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - - _alpm_log(handle, ALPM_LOG_DEBUG, "archive: %s\n", pkgfile); - if(archive_read_open_filename(archive, pkgfile, - ALPM_BUFFER_SIZE) != ARCHIVE_OK) { - handle->pm_errno = ALPM_ERR_PKG_OPEN; + fd = _alpm_open_archive(db->handle, pkgfile, &buf, + &archive, ALPM_ERR_PKG_OPEN); + if(fd < 0) { ret = -1; goto cleanup; } /* save the cwd so we can restore it later */ - do { - cwdfd = open(".", O_RDONLY); - } while(cwdfd == -1 && errno == EINTR); + OPEN(cwdfd, ".", O_RDONLY); if(cwdfd < 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } @@ -554,6 +544,8 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, if(chdir(handle->root) != 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), handle->root, strerror(errno)); + archive_read_finish(archive); + CLOSE(fd); ret = -1; goto cleanup; } @@ -595,6 +587,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, errors += extract_single_file(handle, archive, entry, newpkg, oldpkg); } archive_read_finish(archive); + CLOSE(fd); /* restore the old cwd if we have it */ if(cwdfd >= 0) { @@ -602,7 +595,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, _alpm_log(handle, ALPM_LOG_ERROR, _("could not restore working directory (%s)\n"), strerror(errno)); } - close(cwdfd); + CLOSE(cwdfd); } if(errors) { diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h index 77a3d22a..d1368e8a 100644 --- a/lib/libalpm/add.h +++ b/lib/libalpm/add.h @@ -1,7 +1,7 @@ /* * add.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index 38843342..c58a4069 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -1,7 +1,7 @@ /* * alpm.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #ifdef HAVE_LIBCURL #include <curl/curl.h> #endif @@ -47,9 +45,9 @@ * @return a context handle on success, NULL on error, err will be set if provided */ alpm_handle_t SYMEXPORT *alpm_initialize(const char *root, const char *dbpath, - enum _alpm_errno_t *err) + alpm_errno_t *err) { - enum _alpm_errno_t myerr; + alpm_errno_t myerr; const char *lf = "db.lck"; size_t lockfilelen; alpm_handle_t *myhandle = _alpm_handle_new(); @@ -108,7 +106,7 @@ int SYMEXPORT alpm_release(alpm_handle_t *myhandle) myhandle->db_local = NULL; } - if(alpm_db_unregister_all(myhandle) == -1) { + if(alpm_unregister_all_syncdbs(myhandle) == -1) { ret = -1; } diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 6df3e1f5..bb792cf3 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -1,7 +1,7 @@ /* * alpm.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -27,14 +27,12 @@ extern "C" { #endif -#include <sys/types.h> /* for off_t */ -#include <time.h> /* for time_t */ -#include <stdarg.h> /* for va_list */ +#include <stdint.h> /* int64_t */ +#include <sys/types.h> /* off_t */ +#include <stdarg.h> /* va_list */ #include <alpm_list.h> -#define DEPRECATED __attribute__((deprecated)) - /* * Arch Linux Package Management library */ @@ -44,15 +42,14 @@ extern "C" { * @{ */ +typedef int64_t alpm_time_t; + /* * Enumerations * These ones are used in multiple contexts, so are forward-declared. */ -/** - * Install reasons. - * Why the package was installed. - */ +/** Package install reasons. */ typedef enum _alpm_pkgreason_t { /** Explicitly requested by the user. */ ALPM_PKG_REASON_EXPLICIT = 0, @@ -60,12 +57,22 @@ typedef enum _alpm_pkgreason_t { ALPM_PKG_REASON_DEPEND = 1 } alpm_pkgreason_t; +/** Location a package object was loaded from. */ typedef enum _alpm_pkgfrom_t { - PKG_FROM_FILE = 1, - PKG_FROM_LOCALDB, - PKG_FROM_SYNCDB + ALPM_PKG_FROM_FILE = 1, + ALPM_PKG_FROM_LOCALDB, + ALPM_PKG_FROM_SYNCDB } alpm_pkgfrom_t; +/** Location a package object was loaded from. */ +typedef enum _alpm_pkgvalidation_t { + ALPM_PKG_VALIDATION_UNKNOWN = 0, + ALPM_PKG_VALIDATION_NONE = (1 << 0), + ALPM_PKG_VALIDATION_MD5SUM = (1 << 1), + ALPM_PKG_VALIDATION_SHA256SUM = (1 << 2), + ALPM_PKG_VALIDATION_SIGNATURE = (1 << 3) +} alpm_pkgvalidation_t; + /** Types of version constraints in dependency specs. */ typedef enum _alpm_depmod_t { /** No version constraint */ @@ -92,9 +99,7 @@ typedef enum _alpm_fileconflicttype_t { ALPM_FILECONFLICT_FILESYSTEM } alpm_fileconflicttype_t; -/** - * PGP signature verification options - */ +/** PGP signature verification options */ typedef enum _alpm_siglevel_t { ALPM_SIG_PACKAGE = (1 << 0), ALPM_SIG_PACKAGE_OPTIONAL = (1 << 1), @@ -109,9 +114,7 @@ typedef enum _alpm_siglevel_t { ALPM_SIG_USE_DEFAULT = (1 << 31) } alpm_siglevel_t; -/** - * PGP signature verification status return codes - */ +/** PGP signature verification status return codes */ typedef enum _alpm_sigstatus_t { ALPM_SIGSTATUS_VALID, ALPM_SIGSTATUS_KEY_EXPIRED, @@ -121,9 +124,7 @@ typedef enum _alpm_sigstatus_t { ALPM_SIGSTATUS_INVALID } alpm_sigstatus_t; -/** - * PGP signature verification status return codes - */ +/** PGP signature verification status return codes */ typedef enum _alpm_sigvalidity_t { ALPM_SIGVALIDITY_FULL, ALPM_SIGVALIDITY_MARGINAL, @@ -144,6 +145,7 @@ typedef struct __alpm_trans_t alpm_trans_t; typedef struct _alpm_depend_t { char *name; char *version; + char *desc; unsigned long name_hash; alpm_depmod_t mod; } alpm_depend_t; @@ -152,7 +154,7 @@ typedef struct _alpm_depend_t { typedef struct _alpm_depmissing_t { char *target; alpm_depend_t *depend; - /* this is used in case of remove dependency error only */ + /* this is used only in the case of a remove dependency error */ char *causingpkg; } alpm_depmissing_t; @@ -222,11 +224,15 @@ typedef struct _alpm_pgpkey_t { char *uid; char *name; char *email; - time_t created; - time_t expires; + alpm_time_t created; + alpm_time_t expires; + unsigned int length; + unsigned int revoked; + char pubkey_algo; } alpm_pgpkey_t; -/** Signature result. Contains the key, status, and validity of a given +/** + * Signature result. Contains the key, status, and validity of a given * signature. */ typedef struct _alpm_sigresult_t { @@ -235,7 +241,8 @@ typedef struct _alpm_sigresult_t { alpm_sigvalidity_t validity; } alpm_sigresult_t; -/** Signature list. Contains the number of signatures found and a pointer to an +/** + * Signature list. Contains the number of signatures found and a pointer to an * array of results. The array is of size count. */ typedef struct _alpm_siglist_t { @@ -247,9 +254,7 @@ typedef struct _alpm_siglist_t { * Logging facilities */ -/** - * Logging Levels - */ +/** Logging Levels */ typedef enum _alpm_loglevel_t { ALPM_LOG_ERROR = 1, ALPM_LOG_WARNING = (1 << 1), @@ -260,7 +265,8 @@ typedef enum _alpm_loglevel_t { typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list); int alpm_logaction(alpm_handle_t *handle, const char *fmt, ...); -/** Events. +/** + * Events. * NULL parameters are passed to in all events unless specified otherwise. */ typedef enum _alpm_event_t { @@ -341,13 +347,18 @@ typedef enum _alpm_event_t { /** Disk space usage will be computed for a package */ ALPM_EVENT_DISKSPACE_START, /** Disk space usage was computed for a package */ - ALPM_EVENT_DISKSPACE_DONE, + ALPM_EVENT_DISKSPACE_DONE } alpm_event_t; /** Event callback */ typedef void (*alpm_cb_event)(alpm_event_t, void *, void *); -/** Questions */ +/** + * Questions. + * Unlike the events or progress enumerations, this enum has bitmask values + * so a frontend can use a bitmask map to supply preselected answers to the + * different types of questions. + */ typedef enum _alpm_question_t { ALPM_QUESTION_INSTALL_IGNOREPKG = 1, ALPM_QUESTION_REPLACE_PKG = (1 << 1), @@ -370,7 +381,7 @@ typedef enum _alpm_progress_t { ALPM_PROGRESS_CONFLICTS_START, ALPM_PROGRESS_DISKSPACE_START, ALPM_PROGRESS_INTEGRITY_START, - ALPM_PROGRESS_LOAD_START, + ALPM_PROGRESS_LOAD_START } alpm_progress_t; /** Progress callback */ @@ -530,8 +541,8 @@ const char *alpm_option_get_arch(alpm_handle_t *handle); /** Sets the targeted architecture. */ int alpm_option_set_arch(alpm_handle_t *handle, const char *arch); -int alpm_option_get_usedelta(alpm_handle_t *handle); -int alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta); +double alpm_option_get_deltaratio(alpm_handle_t *handle); +int alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio); int alpm_option_get_checkspace(alpm_handle_t *handle); int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace); @@ -552,7 +563,7 @@ int alpm_option_set_default_siglevel(alpm_handle_t *handle, alpm_siglevel_t leve * libalpm functions. * @return a reference to the local database */ -alpm_db_t *alpm_option_get_localdb(alpm_handle_t *handle); +alpm_db_t *alpm_get_localdb(alpm_handle_t *handle); /** Get the list of sync databases. * Returns a list of alpm_db_t structures, one for each registered @@ -560,7 +571,7 @@ alpm_db_t *alpm_option_get_localdb(alpm_handle_t *handle); * @param handle the context handle * @return a reference to an internal list of alpm_db_t structures */ -alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle); +alpm_list_t *alpm_get_syncdbs(alpm_handle_t *handle); /** Register a sync database of packages. * @param handle the context handle @@ -569,20 +580,20 @@ alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle); * database; note that this must be a '.sig' file type verification * @return an alpm_db_t* on success (the value), NULL on error */ -alpm_db_t *alpm_db_register_sync(alpm_handle_t *handle, const char *treename, +alpm_db_t *alpm_register_syncdb(alpm_handle_t *handle, const char *treename, alpm_siglevel_t level); -/** Unregister a package database. - * @param db pointer to the package database to unregister +/** Unregister all package databases. + * @param handle the context handle * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_db_unregister(alpm_db_t *db); +int alpm_unregister_all_syncdbs(alpm_handle_t *handle); -/** Unregister all package databases. - * @param handle the context handle +/** Unregister a package database. + * @param db pointer to the package database to unregister * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_db_unregister_all(alpm_handle_t *handle); +int alpm_db_unregister(alpm_db_t *db); /** Get the name of a package database. * @param db pointer to the package database @@ -635,7 +646,7 @@ alpm_list_t *alpm_db_get_pkgcache(alpm_db_t *db); * @param name of the group * @return the groups entry on success, NULL on error */ -alpm_group_t *alpm_db_readgroup(alpm_db_t *db, const char *name); +alpm_group_t *alpm_db_get_group(alpm_db_t *db, const char *name); /** Get the group cache of a package database. * @param db pointer to the package database to get the group from @@ -648,16 +659,7 @@ alpm_list_t *alpm_db_get_groupcache(alpm_db_t *db); * @param needles a list of regular expressions to search for * @return the list of packages matching all regular expressions on success, NULL on error */ -alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles); - -/** Set install reason for a package in db. - * @param handle the context handle - * @param pkg the package to update - * @param reason the new install reason - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg, - alpm_pkgreason_t reason); +alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t *needles); /** @} */ @@ -754,13 +756,13 @@ const char *alpm_pkg_get_url(alpm_pkg_t *pkg); * @param pkg a pointer to package * @return the timestamp of the build time */ -time_t alpm_pkg_get_builddate(alpm_pkg_t *pkg); +alpm_time_t alpm_pkg_get_builddate(alpm_pkg_t *pkg); /** Returns the install timestamp of the package. * @param pkg a pointer to package * @return the timestamp of the install time */ -time_t alpm_pkg_get_installdate(alpm_pkg_t *pkg); +alpm_time_t alpm_pkg_get_installdate(alpm_pkg_t *pkg); /** Returns the packager's name. * @param pkg a pointer to package @@ -827,7 +829,7 @@ alpm_list_t *alpm_pkg_get_depends(alpm_pkg_t *pkg); /** Returns the list of package optional dependencies. * @param pkg a pointer to package - * @return a reference to an internal list of strings. + * @return a reference to an internal list of alpm_depend_t structures. */ alpm_list_t *alpm_pkg_get_optdepends(alpm_pkg_t *pkg); @@ -887,6 +889,12 @@ alpm_db_t *alpm_pkg_get_db(alpm_pkg_t *pkg); */ const char *alpm_pkg_get_base64_sig(alpm_pkg_t *pkg); +/** Returns the method used to validate a package during install. + * @param pkg a pointer to package + * @return an enum member giving the validation method + */ +alpm_pkgvalidation_t alpm_pkg_get_validation(alpm_pkg_t *pkg); + /* End of alpm_pkg_t accessors */ /* @} */ @@ -928,6 +936,16 @@ off_t alpm_pkg_download_size(alpm_pkg_t *newpkg); alpm_list_t *alpm_pkg_unused_deltas(alpm_pkg_t *pkg); +/** Set install reason for a package in the local database. + * The provided package object must be from the local database or this method + * will fail. The write to the local database is performed immediately. + * @param pkg the package to update + * @param reason the new install reason + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason); + + /* End of alpm_pkg */ /** @} */ @@ -1107,13 +1125,13 @@ char *alpm_dep_compute_string(const alpm_depend_t *dep); */ /* checksums */ -char *alpm_compute_md5sum(const char *name); +char *alpm_compute_md5sum(const char *filename); char *alpm_compute_sha256sum(const char *filename); /** @addtogroup alpm_api_errors Error Codes * @{ */ -enum _alpm_errno_t { +typedef enum _alpm_errno_t { ALPM_ERR_MEMORY = 1, ALPM_ERR_SYSTEM, ALPM_ERR_BADPERMS, @@ -1177,19 +1195,19 @@ enum _alpm_errno_t { ALPM_ERR_LIBCURL, ALPM_ERR_EXTERNAL_DOWNLOAD, ALPM_ERR_GPGME -}; +} alpm_errno_t; /** Returns the current error code from the handle. */ -enum _alpm_errno_t alpm_errno(alpm_handle_t *handle); +alpm_errno_t alpm_errno(alpm_handle_t *handle); /** Returns the string corresponding to an error number. */ -const char *alpm_strerror(enum _alpm_errno_t err); +const char *alpm_strerror(alpm_errno_t err); /* End of alpm_api_errors */ /** @} */ alpm_handle_t *alpm_initialize(const char *root, const char *dbpath, - enum _alpm_errno_t *err); + alpm_errno_t *err); int alpm_release(alpm_handle_t *handle); enum alpm_caps { diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 3aa4f9bc..39eded13 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -1,7 +1,7 @@ /* * alpm_list.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -204,7 +204,8 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second) * * @return the resultant list */ -alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, alpm_list_fn_cmp fn) +alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, + alpm_list_fn_cmp fn) { alpm_list_t *newlist, *lp, *tail_ptr, *left_tail_ptr, *right_tail_ptr; @@ -273,20 +274,26 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a * * @return the resultant list */ -alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, alpm_list_fn_cmp fn) +alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, + alpm_list_fn_cmp fn) { if(n > 1) { - alpm_list_t *left = list; - alpm_list_t *lastleft = alpm_list_nth(list, n/2 - 1); - alpm_list_t *right = lastleft->next; + size_t half = n / 2; + size_t i = half - 1; + alpm_list_t *left = list, *lastleft = list, *right; + + while(i--) { + lastleft = lastleft->next; + } + right = lastleft->next; /* tidy new lists */ lastleft->next = NULL; right->prev = left->prev; left->prev = lastleft; - left = alpm_list_msort(left, n/2, fn); - right = alpm_list_msort(right, n - (n/2), fn); + left = alpm_list_msort(left, half, fn); + right = alpm_list_msort(right, n - half, fn); list = alpm_list_mmerge(left, right, fn); } return list; @@ -579,19 +586,6 @@ alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list) } } -/** - * @brief Get the data member of a list node. - * - * @param node the list node - * - * @return the contained data, or NULL if none - */ -void SYMEXPORT *alpm_list_getdata(const alpm_list_t *node) -{ - if(node == NULL) return NULL; - return node->data; -} - /* Misc */ /** diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index cd7b0291..8f743a28 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -1,7 +1,7 @@ /* * alpm_list.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -71,7 +71,6 @@ alpm_list_t *alpm_list_nth(const alpm_list_t *list, size_t n); alpm_list_t *alpm_list_next(const alpm_list_t *list); alpm_list_t *alpm_list_previous(const alpm_list_t *list); alpm_list_t *alpm_list_last(const alpm_list_t *list); -void *alpm_list_getdata(const alpm_list_t *entry); /* misc */ size_t alpm_list_count(const alpm_list_t *list); diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c index 728c1d05..98b5f5e3 100644 --- a/lib/libalpm/backup.c +++ b/lib/libalpm/backup.c @@ -1,7 +1,7 @@ /* * backup.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2005 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <string.h> diff --git a/lib/libalpm/backup.h b/lib/libalpm/backup.h index 0b84a68c..c539406d 100644 --- a/lib/libalpm/backup.h +++ b/lib/libalpm/backup.h @@ -1,7 +1,7 @@ /* * backup.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/base64.c b/lib/libalpm/base64.c index 5c9fa814..32c44459 100644 --- a/lib/libalpm/base64.c +++ b/lib/libalpm/base64.c @@ -32,6 +32,8 @@ * * removal of SELF_TEST code */ +#include <stdint.h> + #include "base64.h" static const unsigned char base64_enc_map[64] = @@ -62,6 +64,7 @@ static const unsigned char base64_dec_map[128] = 49, 50, 51, 127, 127, 127, 127, 127 }; +#if 0 /* * Encode a buffer into base64 format */ @@ -124,6 +127,7 @@ int base64_encode( unsigned char *dst, size_t *dlen, return( 0 ); } +#endif /* * Decode a base64-formatted buffer @@ -131,8 +135,8 @@ int base64_encode( unsigned char *dst, size_t *dlen, int base64_decode( unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen ) { - size_t i, j, n; - unsigned long x; + size_t i, n; + uint32_t j, x; unsigned char *p; for( i = j = n = 0; i < slen; i++ ) diff --git a/lib/libalpm/base64.h b/lib/libalpm/base64.h index 406aefa1..df684ab7 100644 --- a/lib/libalpm/base64.h +++ b/lib/libalpm/base64.h @@ -30,6 +30,7 @@ #define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x0010 /**< Output buffer too small. */ #define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x0012 /**< Invalid character in input. */ +#if 0 /** * \brief Encode a buffer into base64 format * @@ -47,6 +48,7 @@ */ int base64_encode( unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen ); +#endif /** * \brief Decode a base64-formatted buffer diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 56cf38bb..39df15b0 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -1,7 +1,7 @@ /* * be_local.c : backend for the local database * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <unistd.h> #include <stdio.h> #include <stdlib.h> @@ -28,7 +26,6 @@ #include <stdint.h> /* intmax_t */ #include <sys/stat.h> #include <dirent.h> -#include <time.h> #include <limits.h> /* PATH_MAX */ /* libalpm */ @@ -69,13 +66,13 @@ static const char *_cache_get_url(alpm_pkg_t *pkg) return pkg->url; } -static time_t _cache_get_builddate(alpm_pkg_t *pkg) +static alpm_time_t _cache_get_builddate(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, 0); return pkg->builddate; } -static time_t _cache_get_installdate(alpm_pkg_t *pkg) +static alpm_time_t _cache_get_installdate(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, 0); return pkg->installdate; @@ -105,6 +102,12 @@ static alpm_pkgreason_t _cache_get_reason(alpm_pkg_t *pkg) return pkg->reason; } +static alpm_pkgvalidation_t _cache_get_validation(alpm_pkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, -1); + return pkg->validation; +} + static alpm_list_t *_cache_get_licenses(alpm_pkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); @@ -226,6 +229,7 @@ static struct pkg_operations local_pkg_ops = { .get_arch = _cache_get_arch, .get_isize = _cache_get_isize, .get_reason = _cache_get_reason, + .get_validation = _cache_get_validation, .has_scriptlet = _cache_has_scriptlet, .get_licenses = _cache_get_licenses, .get_groups = _cache_get_groups, @@ -401,12 +405,11 @@ static int local_db_populate(alpm_db_t *db) rewinddir(dbdir); } if(est_count >= 2) { - /* subtract the two extra pointers to get # of children */ + /* subtract the '.' and '..' pointers to get # of children */ est_count -= 2; } - /* initialize hash at 50% full */ - db->pkgcache = _alpm_pkghash_create(est_count * 2); + db->pkgcache = _alpm_pkghash_create(est_count); if(db->pkgcache == NULL){ closedir(dbdir); RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); @@ -445,7 +448,7 @@ static int local_db_populate(alpm_db_t *db) continue; } - pkg->origin = PKG_FROM_LOCALDB; + pkg->origin = ALPM_PKG_FROM_LOCALDB; pkg->origin_data.db = db; pkg->ops = &local_pkg_ops; pkg->handle = db->handle; @@ -475,7 +478,8 @@ static int local_db_populate(alpm_db_t *db) } /* Note: the return value must be freed by the caller */ -char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filename) +char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, + const char *filename) { size_t len; char *pkgpath; @@ -522,7 +526,6 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { FILE *fp = NULL; char line[1024]; - char *pkgpath; alpm_db_t *db = info->origin_data.db; /* bitmask logic here: @@ -541,18 +544,10 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) return -1; } - _alpm_log(db->handle, ALPM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n", + _alpm_log(db->handle, ALPM_LOG_FUNCTION, + "loading package data for %s : level=0x%x\n", info->name, inforeq); - pkgpath = _alpm_local_db_pkgpath(db, info, NULL); - if(!pkgpath || access(pkgpath, F_OK)) { - /* directory doesn't exist or can't be opened */ - _alpm_log(db->handle, ALPM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", - info->name, info->version, db->treename); - goto error; - } - free(pkgpath); - /* clear out 'line', to be certain - and to make valgrind happy */ memset(line, 0, sizeof(line)); @@ -606,6 +601,26 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) } else if(strcmp(line, "%REASON%") == 0) { READ_NEXT(); info->reason = (alpm_pkgreason_t)atoi(line); + } else if(strcmp(line, "%VALIDATION%") == 0) { + alpm_list_t *i, *v = NULL; + READ_AND_STORE_ALL(v); + for(i = v; i; i = alpm_list_next(i)) + { + if(strcmp(i->data, "none") == 0) { + info->validation |= ALPM_PKG_VALIDATION_NONE; + } else if(strcmp(i->data, "md5") == 0) { + info->validation |= ALPM_PKG_VALIDATION_MD5SUM; + } else if(strcmp(i->data, "sha256") == 0) { + info->validation |= ALPM_PKG_VALIDATION_SHA256SUM; + } else if(strcmp(i->data, "pgp") == 0) { + info->validation |= ALPM_PKG_VALIDATION_SIGNATURE; + } else { + _alpm_log(db->handle, ALPM_LOG_WARNING, + _("unknown validation type for package %s: %s\n"), + info->name, (const char *)i->data); + } + } + FREELIST(v); } else if(strcmp(line, "%SIZE%") == 0) { READ_NEXT(); info->isize = _alpm_strtoofft(line); @@ -614,7 +629,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) } else if(strcmp(line, "%DEPENDS%") == 0) { READ_AND_SPLITDEP(info->depends); } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - READ_AND_STORE_ALL(info->optdepends); + READ_AND_SPLITDEP(info->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { READ_AND_SPLITDEP(info->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { @@ -638,10 +653,11 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) while(fgets(line, sizeof(line), fp)) { _alpm_strip_newline(line); if(strcmp(line, "%FILES%") == 0) { - size_t files_count = 0, files_size = 0; + size_t files_count = 0, files_size = 0, len; alpm_file_t *files = NULL; - while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) { + while(fgets(line, sizeof(line), fp) && + (len = _alpm_strip_newline(line))) { if(files_count >= files_size) { size_t old_size = files_size; if(files_size == 0) { @@ -659,8 +675,14 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) memset(files + old_size, 0, sizeof(alpm_file_t) * (files_size - old_size)); } - STRDUP(files[files_count].name, line, goto error); - /* TODO: lstat file, get mode/size */ + /* since we know the length of the file string already, + * we can do malloc + memcpy rather than strdup */ + files[files_count].name = malloc(len + 1); + if(files[files_count].name == NULL) { + ALLOC_FAIL(len); + goto error; + } + memcpy(files[files_count].name, line, len + 1); files_count++; } /* attempt to hand back any memory we don't need */ @@ -727,6 +749,23 @@ int _alpm_local_db_prepare(alpm_db_t *db, alpm_pkg_t *info) return retval; } +static void write_deps(FILE *fp, const char *header, alpm_list_t *deplist) +{ + alpm_list_t *lp; + if(!deplist) { + return; + } + fputs(header, fp); + fputc('\n', fp); + for(lp = deplist; lp; lp = lp->next) { + char *depstring = alpm_dep_compute_string(lp->data); + fputs(depstring, fp); + fputc('\n', fp); + free(depstring); + } + fputc('\n', fp); +} + int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { FILE *fp = NULL; @@ -764,18 +803,10 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq if(info->groups) { fputs("%GROUPS%\n", fp); for(lp = info->groups; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + fputs(lp->data, fp); + fputc('\n', fp); } - fprintf(fp, "\n"); - } - if(info->replaces) { - fputs("%REPLACES%\n", fp); - for(lp = info->replaces; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); - } - fprintf(fp, "\n"); + fputc('\n', fp); } if(info->url) { fprintf(fp, "%%URL%%\n" @@ -784,9 +815,10 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq if(info->licenses) { fputs("%LICENSE%\n", fp); for(lp = info->licenses; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + fputs(lp->data, fp); + fputc('\n', fp); } - fprintf(fp, "\n"); + fputc('\n', fp); } if(info->arch) { fprintf(fp, "%%ARCH%%\n" @@ -794,11 +826,11 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq } if(info->builddate) { fprintf(fp, "%%BUILDDATE%%\n" - "%ld\n\n", info->builddate); + "%jd\n\n", (intmax_t)info->builddate); } if(info->installdate) { fprintf(fp, "%%INSTALLDATE%%\n" - "%ld\n\n", info->installdate); + "%jd\n\n", (intmax_t)info->installdate); } if(info->packager) { fprintf(fp, "%%PACKAGER%%\n" @@ -813,41 +845,29 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq fprintf(fp, "%%REASON%%\n" "%u\n\n", info->reason); } - if(info->depends) { - fputs("%DEPENDS%\n", fp); - for(lp = info->depends; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); + if(info->validation) { + fputs("%VALIDATION%\n", fp); + if(info->validation & ALPM_PKG_VALIDATION_NONE) { + fputs("none\n", fp); } - fprintf(fp, "\n"); - } - if(info->optdepends) { - fputs("%OPTDEPENDS%\n", fp); - for(lp = info->optdepends; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + if(info->validation & ALPM_PKG_VALIDATION_MD5SUM) { + fputs("md5\n", fp); } - fprintf(fp, "\n"); - } - if(info->conflicts) { - fputs("%CONFLICTS%\n", fp); - for(lp = info->conflicts; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); + if(info->validation & ALPM_PKG_VALIDATION_SHA256SUM) { + fputs("sha256\n", fp); } - fprintf(fp, "\n"); - } - if(info->provides) { - fputs("%PROVIDES%\n", fp); - for(lp = info->provides; lp; lp = lp->next) { - char *depstring = alpm_dep_compute_string(lp->data); - fprintf(fp, "%s\n", depstring); - free(depstring); + if(info->validation & ALPM_PKG_VALIDATION_SIGNATURE) { + fputs("pgp\n", fp); } - fprintf(fp, "\n"); + fputc('\n', fp); } + write_deps(fp, "%REPLACES%", info->replaces); + write_deps(fp, "%DEPENDS%", info->depends); + write_deps(fp, "%OPTDEPENDS%", info->optdepends); + write_deps(fp, "%CONFLICTS%", info->conflicts); + write_deps(fp, "%PROVIDES%", info->provides); + fclose(fp); fp = NULL; } @@ -868,20 +888,21 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq free(path); if(info->files.count) { size_t i; - fprintf(fp, "%%FILES%%\n"); + fputs("%FILES%\n", fp); for(i = 0; i < info->files.count; i++) { const alpm_file_t *file = info->files.files + i; - fprintf(fp, "%s\n", file->name); + fputs(file->name, fp); + fputc('\n', fp); } - fprintf(fp, "\n"); + fputc('\n', fp); } if(info->backup) { - fprintf(fp, "%%BACKUP%%\n"); + fputs("%BACKUP%\n", fp); for(lp = info->backup; lp; lp = lp->next) { const alpm_backup_t *backup = lp->data; fprintf(fp, "%s\t%s\n", backup->name, backup->hash); } - fprintf(fp, "\n"); + fputc('\n', fp); } fclose(fp); fp = NULL; @@ -903,17 +924,71 @@ cleanup: int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_t *info) { int ret = 0; - char *pkgpath = _alpm_local_db_pkgpath(db, info, NULL); + DIR *dirp; + struct dirent *dp; + char *pkgpath; + size_t pkgpath_len; - /* TODO explicit file removes and then an rmdir? */ - ret = _alpm_rmrf(pkgpath); - free(pkgpath); - if(ret != 0) { + pkgpath = _alpm_local_db_pkgpath(db, info, NULL); + if(!pkgpath) { + return -1; + } + pkgpath_len = strlen(pkgpath); + + dirp = opendir(pkgpath); + if(!dirp) { + return -1; + } + /* go through the local DB entry, removing the files within, which we know + * are not nested directories of any kind. */ + for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { + if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) { + char name[PATH_MAX]; + if(pkgpath_len + strlen(dp->d_name) + 2 > PATH_MAX) { + /* file path is too long to remove, hmm. */ + ret = -1; + } else { + sprintf(name, "%s/%s", pkgpath, dp->d_name); + if(unlink(name)) { + ret = -1; + } + } + } + } + closedir(dirp); + + /* after removing all enclosed files, we can remove the directory itself. */ + if(rmdir(pkgpath)) { ret = -1; } + free(pkgpath); return ret; } +int SYMEXPORT alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason) +{ + ASSERT(pkg != NULL, return -1); + ASSERT(pkg->origin == ALPM_PKG_FROM_LOCALDB, + RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg->origin_data.db == pkg->handle->db_local, + RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); + + _alpm_log(pkg->handle, ALPM_LOG_DEBUG, + "setting install reason %u for %s\n", reason, pkg->name); + if(alpm_pkg_get_reason(pkg) == reason) { + /* we are done */ + return 0; + } + /* set reason (in pkgcache) */ + pkg->reason = reason; + /* write DESC */ + if(_alpm_local_db_write(pkg->handle->db_local, pkg, INFRQ_DESC)) { + RET_ERR(pkg->handle, ALPM_ERR_DB_WRITE, -1); + } + + return 0; +} + struct db_operations local_db_ops = { .validate = local_db_validate, .populate = local_db_populate, diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 93b762a1..bcb884f4 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -1,7 +1,7 @@ /* * be_package.c : backend for packages * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,11 +18,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <string.h> #include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> /* libarchive */ #include <archive.h> @@ -35,7 +36,12 @@ #include "log.h" #include "handle.h" #include "package.h" -#include "deps.h" /* _alpm_splitdep */ +#include "deps.h" + +struct package_changelog { + struct archive *archive; + int fd; +}; /** * Open a package changelog for reading. Similar to fopen in functionality, @@ -47,31 +53,38 @@ static void *_package_changelog_open(alpm_pkg_t *pkg) { ASSERT(pkg != NULL, return NULL); - struct archive *archive = NULL; + struct package_changelog *changelog; + struct archive *archive; struct archive_entry *entry; const char *pkgfile = pkg->origin_data.file; + struct stat buf; + int fd; - if((archive = archive_read_new()) == NULL) { - RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, NULL); - } - - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - - if(archive_read_open_filename(archive, pkgfile, - ALPM_BUFFER_SIZE) != ARCHIVE_OK) { - RET_ERR(pkg->handle, ALPM_ERR_PKG_OPEN, NULL); + fd = _alpm_open_archive(pkg->handle, pkgfile, &buf, + &archive, ALPM_ERR_PKG_OPEN); + if(fd < 0) { + return NULL; } while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { const char *entry_name = archive_entry_pathname(entry); if(strcmp(entry_name, ".CHANGELOG") == 0) { - return archive; + changelog = malloc(sizeof(struct package_changelog)); + if(!changelog) { + pkg->handle->pm_errno = ALPM_ERR_MEMORY; + archive_read_finish(archive); + CLOSE(fd); + return NULL; + } + changelog->archive = archive; + changelog->fd = fd; + return changelog; } } /* we didn't find a changelog */ archive_read_finish(archive); + CLOSE(fd); errno = ENOENT; return NULL; @@ -89,7 +102,8 @@ static void *_package_changelog_open(alpm_pkg_t *pkg) static size_t _package_changelog_read(void *ptr, size_t size, const alpm_pkg_t UNUSED *pkg, void *fp) { - ssize_t sret = archive_read_data((struct archive *)fp, ptr, size); + struct package_changelog *changelog = fp; + ssize_t sret = archive_read_data(changelog->archive, ptr, size); /* Report error (negative values) */ if(sret < 0) { RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, 0); @@ -107,7 +121,12 @@ static size_t _package_changelog_read(void *ptr, size_t size, */ static int _package_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp) { - return archive_read_finish((struct archive *)fp); + int ret; + struct package_changelog *changelog = fp; + ret = archive_read_finish(changelog->archive); + CLOSE(changelog->fd); + free(changelog); + return ret; } /** Package file operations struct accessor. We implement this as a method @@ -152,18 +171,21 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t * size_t len = _alpm_strip_newline(buf.line); linenum++; - if(len == 0 || buf.line[0] == '#') { + key = buf.line; + if(len == 0 || key[0] == '#') { continue; } - ptr = buf.line; - key = strsep(&ptr, "="); - if(key == NULL || ptr == NULL) { - _alpm_log(handle, ALPM_LOG_DEBUG, "%s: syntax error in description file line %d\n", - newpkg->name ? newpkg->name : "error", linenum); + /* line is always in this format: "key = value" + * we can be sure the " = " exists, so look for that */ + ptr = memchr(key, ' ', len); + if(!ptr || (size_t)(ptr - key + 2) > len || memcmp(ptr, " = ", 3) != 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "%s: syntax error in description file line %d\n", + newpkg->name ? newpkg->name : "error", linenum); } else { - key = _alpm_strtrim(key); - while(*ptr == ' ') ptr++; - ptr = _alpm_strtrim(ptr); + /* NULL the end of the key portion, move ptr to start of value */ + *ptr = '\0'; + ptr += 3; if(strcmp(key, "pkgname") == 0) { STRDUP(newpkg->name, ptr, return -1); newpkg->name_hash = _alpm_hash_sdbm(newpkg->name); @@ -192,7 +214,8 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t * alpm_depend_t *dep = _alpm_splitdep(ptr); newpkg->depends = alpm_list_add(newpkg->depends, dep); } else if(strcmp(key, "optdepend") == 0) { - newpkg->optdepends = alpm_list_add(newpkg->optdepends, strdup(ptr)); + alpm_depend_t *optdep = _alpm_splitdep(ptr); + newpkg->optdepends = alpm_list_add(newpkg->optdepends, optdep); } else if(strcmp(key, "conflict") == 0) { alpm_depend_t *conflict = _alpm_splitdep(ptr); newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict); @@ -280,11 +303,12 @@ static alpm_file_t *files_msort(alpm_file_t *files, size_t n) * sha256sum, and/or base64 signature) * @param level the required level of signature verification * @param sigdata signature data from the package to pass back + * @param validation successful validations performed on the package file * @return 0 if package is fully valid, -1 and pm_errno otherwise */ int _alpm_pkg_validate_internal(alpm_handle_t *handle, const char *pkgfile, alpm_pkg_t *syncpkg, alpm_siglevel_t level, - alpm_siglist_t **sigdata) + alpm_siglist_t **sigdata, alpm_pkgvalidation_t *validation) { int has_sig; handle->pm_errno = 0; @@ -294,8 +318,15 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle, } /* attempt to access the package file, ensure it exists */ - if(access(pkgfile, R_OK) != 0) { - RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, -1); + if(_alpm_access(handle, NULL, pkgfile, R_OK) != 0) { + if(errno == ENOENT) { + handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND; + } else if(errno == EACCES) { + handle->pm_errno = ALPM_ERR_BADPERMS; + } else { + handle->pm_errno = ALPM_ERR_PKG_OPEN; + } + return -1; } /* can we get away with skipping checksums? */ @@ -316,17 +347,23 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle, if(syncpkg->md5sum && !syncpkg->sha256sum) { _alpm_log(handle, ALPM_LOG_DEBUG, "md5sum: %s\n", syncpkg->md5sum); _alpm_log(handle, ALPM_LOG_DEBUG, "checking md5sum for %s\n", pkgfile); - if(_alpm_test_checksum(pkgfile, syncpkg->md5sum, ALPM_CSUM_MD5) != 0) { + if(_alpm_test_checksum(pkgfile, syncpkg->md5sum, ALPM_PKG_VALIDATION_MD5SUM) != 0) { RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1); } + if(validation) { + *validation |= ALPM_PKG_VALIDATION_MD5SUM; + } } if(syncpkg->sha256sum) { _alpm_log(handle, ALPM_LOG_DEBUG, "sha256sum: %s\n", syncpkg->sha256sum); _alpm_log(handle, ALPM_LOG_DEBUG, "checking sha256sum for %s\n", pkgfile); - if(_alpm_test_checksum(pkgfile, syncpkg->sha256sum, ALPM_CSUM_SHA256) != 0) { + if(_alpm_test_checksum(pkgfile, syncpkg->sha256sum, ALPM_PKG_VALIDATION_SHA256SUM) != 0) { RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1); } + if(validation) { + *validation |= ALPM_PKG_VALIDATION_SHA256SUM; + } } } @@ -340,6 +377,13 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle, handle->pm_errno = ALPM_ERR_PKG_INVALID_SIG; return -1; } + if(validation && has_sig) { + *validation |= ALPM_PKG_VALIDATION_SIGNATURE; + } + } + + if (validation && !*validation) { + *validation = ALPM_PKG_VALIDATION_NONE; } return 0; @@ -355,10 +399,10 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle, alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, int full) { - int ret, config = 0; + int ret, fd, config = 0; struct archive *archive; struct archive_entry *entry; - alpm_pkg_t *newpkg = NULL; + alpm_pkg_t *newpkg; struct stat st; size_t files_size = 0; @@ -366,33 +410,26 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL); } - /* attempt to stat the package file, ensure it exists */ - if(stat(pkgfile, &st) == 0) { - newpkg = _alpm_pkg_new(); - if(newpkg == NULL) { - RET_ERR(handle, ALPM_ERR_MEMORY, NULL); + fd = _alpm_open_archive(handle, pkgfile, &st, &archive, ALPM_ERR_PKG_OPEN); + if(fd < 0) { + if(errno == ENOENT) { + handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND; + } else if(errno == EACCES) { + handle->pm_errno = ALPM_ERR_BADPERMS; + } else { + handle->pm_errno = ALPM_ERR_PKG_OPEN; } - newpkg->filename = strdup(pkgfile); - newpkg->size = st.st_size; - } else { - /* couldn't stat the pkgfile, return an error */ - RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, NULL); - } - - /* try to create an archive object to read in the package */ - if((archive = archive_read_new()) == NULL) { - _alpm_pkg_free(newpkg); - RET_ERR(handle, ALPM_ERR_LIBARCHIVE, NULL); + return NULL; } - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - - if(archive_read_open_filename(archive, pkgfile, - ALPM_BUFFER_SIZE) != ARCHIVE_OK) { - handle->pm_errno = ALPM_ERR_PKG_OPEN; + newpkg = _alpm_pkg_new(); + if(newpkg == NULL) { + handle->pm_errno = ALPM_ERR_MEMORY; goto error; } + STRDUP(newpkg->filename, pkgfile, + handle->pm_errno = ALPM_ERR_MEMORY; goto error); + newpkg->size = st.st_size; _alpm_log(handle, ALPM_LOG_DEBUG, "starting package load for %s\n", pkgfile); @@ -481,13 +518,15 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, } archive_read_finish(archive); + CLOSE(fd); /* internal fields for package struct */ - newpkg->origin = PKG_FROM_FILE; + newpkg->origin = ALPM_PKG_FROM_FILE; newpkg->origin_data.file = strdup(pkgfile); newpkg->ops = get_file_pkg_ops(); newpkg->handle = handle; newpkg->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_SCRIPTLET; + newpkg->validation = ALPM_PKG_VALIDATION_NONE; if(full) { if(newpkg->files.files) { @@ -510,6 +549,9 @@ pkg_invalid: error: _alpm_pkg_free(newpkg); archive_read_finish(archive); + if(fd >= 0) { + CLOSE(fd); + } return NULL; } @@ -517,10 +559,13 @@ error: int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full, alpm_siglevel_t level, alpm_pkg_t **pkg) { + alpm_pkgvalidation_t validation = 0; + CHECK_HANDLE(handle, return -1); ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); - if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL) == -1) { + if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL, + &validation) == -1) { /* pm_errno is set by pkg_validate */ return -1; } @@ -529,6 +574,7 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful /* pm_errno is set by pkg_load */ return -1; } + (*pkg)->validation = validation; return 0; } diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 3c990246..9fadff54 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -1,7 +1,7 @@ /* * be_sync.c : backend for sync databases * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,10 +18,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <errno.h> +#include <sys/types.h> #include <sys/stat.h> +#include <fcntl.h> #include <unistd.h> /* libarchive */ @@ -86,7 +86,7 @@ static int sync_db_validate(alpm_db_t *db) } /* we can skip any validation if the database doesn't exist */ - if(access(dbpath, R_OK) != 0 && errno == ENOENT) { + if(_alpm_access(db->handle, NULL, dbpath, R_OK) != 0 && errno == ENOENT) { db->status &= ~DB_STATUS_EXISTS; db->status |= DB_STATUS_MISSING; _alpm_log(db->handle, ALPM_LOG_WARNING, @@ -212,6 +212,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db) /* print server + filename into a buffer */ len = strlen(server) + strlen(db->treename) + 5; + /* TODO fix leak syncpath and umask unset */ MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); snprintf(payload.fileurl, len, "%s/%s.db", server, db->treename); payload.handle = handle; @@ -234,6 +235,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db) /* if we downloaded a DB, we want the .sig from the same server */ /* print server + filename into a buffer (leave space for .sig) */ len = strlen(server) + strlen(db->treename) + 9; + /* TODO fix leak syncpath and umask unset */ MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); snprintf(payload.fileurl, len, "%s/%s.db.sig", server, db->treename); payload.handle = handle; @@ -294,6 +296,29 @@ cleanup: static int sync_db_read(alpm_db_t *db, struct archive *archive, struct archive_entry *entry, alpm_pkg_t **likely_pkg); +static alpm_pkgvalidation_t _sync_get_validation(alpm_pkg_t *pkg) +{ + if(pkg->validation) { + return pkg->validation; + } + + if(pkg->md5sum) { + pkg->validation |= ALPM_PKG_VALIDATION_MD5SUM; + } + if(pkg->sha256sum) { + pkg->validation |= ALPM_PKG_VALIDATION_SHA256SUM; + } + if(pkg->base64_sig) { + pkg->validation |= ALPM_PKG_VALIDATION_SIGNATURE; + } + + if(!pkg->validation) { + pkg->validation |= ALPM_PKG_VALIDATION_NONE; + } + + return pkg->validation; +} + static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname, const char **entry_filename, alpm_pkg_t *likely_pkg) { @@ -316,7 +341,8 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname, return NULL; } - if(likely_pkg && strcmp(likely_pkg->name, pkgname) == 0) { + if(likely_pkg && pkgname_hash == likely_pkg->name_hash + && strcmp(likely_pkg->name, pkgname) == 0) { pkg = likely_pkg; } else { pkg = _alpm_pkghash_find(db->pkgcache, pkgname); @@ -331,9 +357,10 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname, pkg->version = pkgver; pkg->name_hash = pkgname_hash; - pkg->origin = PKG_FROM_SYNCDB; + pkg->origin = ALPM_PKG_FROM_SYNCDB; pkg->origin_data.db = db; pkg->ops = &default_pkg_ops; + pkg->ops->get_validation = _sync_get_validation; pkg->handle = db->handle; /* add to the collection */ @@ -348,61 +375,38 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname, return pkg; } -/* - * This is the data table used to generate the estimating function below. - * "Weighted Avg" means averaging the bottom table values; thus each repo, big - * or small, will have equal influence. "Unweighted Avg" means averaging the - * sums of the top table columns, thus each package has equal influence. The - * final values are calculated by (surprise) averaging the averages, because - * why the hell not. - * - * Database Pkgs tar bz2 gz xz - * community 2096 5294080 256391 421227 301296 - * core 180 460800 25257 36850 29356 - * extra 2606 6635520 294647 470818 339392 - * multilib 126 327680 16120 23261 18732 - * testing 76 204800 10902 14348 12100 - * - * Bytes Per Package - * community 2096 2525.80 122.32 200.97 143.75 - * core 180 2560.00 140.32 204.72 163.09 - * extra 2606 2546.25 113.06 180.67 130.23 - * multilib 126 2600.63 127.94 184.61 148.67 - * testing 76 2694.74 143.45 188.79 159.21 - - * Weighted Avg 2585.48 129.42 191.95 148.99 - * Unweighted Avg 2543.39 118.74 190.16 137.93 - * Average of Avgs 2564.44 124.08 191.06 143.46 - */ +/* This function doesn't work as well as one might think, as size of database + * entries varies considerably. Adding signatures nearly doubles the size of a + * single entry; deltas also can make for large variations in size. These + * current values are heavily influenced by Arch Linux; databases with no + * deltas and a single signature per package. */ static size_t estimate_package_count(struct stat *st, struct archive *archive) { - unsigned int per_package; + int per_package; switch(archive_compression(archive)) { case ARCHIVE_COMPRESSION_NONE: - per_package = 2564; + per_package = 3015; break; case ARCHIVE_COMPRESSION_GZIP: - per_package = 191; + case ARCHIVE_COMPRESSION_COMPRESS: + per_package = 464; break; case ARCHIVE_COMPRESSION_BZIP2: - per_package = 124; - break; - case ARCHIVE_COMPRESSION_COMPRESS: - per_package = 193; + per_package = 394; break; case ARCHIVE_COMPRESSION_LZMA: case ARCHIVE_COMPRESSION_XZ: - per_package = 143; + per_package = 400; break; #ifdef ARCHIVE_COMPRESSION_UU case ARCHIVE_COMPRESSION_UU: - per_package = 3543; + per_package = 3015 * 4 / 3; break; #endif default: /* assume it is at least somewhat compressed */ - per_package = 200; + per_package = 500; } return (size_t)((st->st_size / per_package) + 1); } @@ -411,7 +415,7 @@ static int sync_db_populate(alpm_db_t *db) { const char *dbpath; size_t est_count; - int count = 0; + int count, fd; struct stat buf; struct archive *archive; struct archive_entry *entry; @@ -423,38 +427,24 @@ static int sync_db_populate(alpm_db_t *db) if(db->status & DB_STATUS_MISSING) { RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1); } - - if((archive = archive_read_new()) == NULL) { - RET_ERR(db->handle, ALPM_ERR_LIBARCHIVE, -1); - } - - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - dbpath = _alpm_db_path(db); if(!dbpath) { /* pm_errno set in _alpm_db_path() */ return -1; } - _alpm_log(db->handle, ALPM_LOG_DEBUG, "opening database archive %s\n", dbpath); - - if(archive_read_open_filename(archive, dbpath, - ALPM_BUFFER_SIZE) != ARCHIVE_OK) { - _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), dbpath, - archive_error_string(archive)); - archive_read_finish(archive); - RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); - } - if(stat(dbpath, &buf) != 0) { - RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1); + fd = _alpm_open_archive(db->handle, dbpath, &buf, + &archive, ALPM_ERR_DB_OPEN); + if(fd < 0) { + return -1; } est_count = estimate_package_count(&buf, archive); - /* initialize hash at 66% full */ - db->pkgcache = _alpm_pkghash_create(est_count * 3 / 2); + db->pkgcache = _alpm_pkghash_create(est_count); if(db->pkgcache == NULL) { - RET_ERR(db->handle, ALPM_ERR_MEMORY, -1); + db->handle->pm_errno = ALPM_ERR_MEMORY; + count = -1; + goto cleanup; } while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { @@ -473,14 +463,19 @@ static int sync_db_populate(alpm_db_t *db) } count = alpm_list_count(db->pkgcache->list); - if(count > 0) { - db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp); + db->pkgcache->list = alpm_list_msort(db->pkgcache->list, + (size_t)count, _alpm_pkg_cmp); } - archive_read_finish(archive); - _alpm_log(db->handle, ALPM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n", + _alpm_log(db->handle, ALPM_LOG_DEBUG, + "added %d packages to package cache for db '%s'\n", count, db->treename); +cleanup: + archive_read_finish(archive); + if(fd >= 0) { + CLOSE(fd); + } return count; } @@ -595,7 +590,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, } else if(strcmp(line, "%DEPENDS%") == 0) { READ_AND_SPLITDEP(pkg->depends); } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - READ_AND_STORE_ALL(pkg->optdepends); + READ_AND_SPLITDEP(pkg->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { READ_AND_SPLITDEP(pkg->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { @@ -605,7 +600,8 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, while(1) { READ_NEXT(); if(strlen(line) == 0) break; - pkg->deltas = alpm_list_add(pkg->deltas, _alpm_delta_parse(line)); + pkg->deltas = alpm_list_add(pkg->deltas, + _alpm_delta_parse(db->handle, line)); } } } diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 32f6f303..85429029 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -1,7 +1,7 @@ /* * conflict.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org> @@ -22,8 +22,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -318,12 +316,16 @@ const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist, const char *name) { size_t i; - const alpm_file_t *file = filelist->files; - for(i = 0; i < filelist->count; i++) { + const alpm_file_t *file; + + if(!filelist) { + return NULL; + } + + for(file = filelist->files, i = 0; i < filelist->count; file++, i++) { if(strcmp(file->name, name) == 0) { return file; } - file++; } return NULL; } @@ -383,11 +385,14 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, alpm_list_t *i, *conflicts = NULL; size_t numtargs = alpm_list_count(upgrade); size_t current; + size_t rootlen; if(!upgrade) { return NULL; } + rootlen = strlen(handle->root); + /* TODO this whole function needs a huge change, which hopefully will * be possible with real transactions. Right now we only do half as much * here as we do when we actually extract files in add.c with our 12 @@ -461,8 +466,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, int resolved_conflict = 0; struct stat lsbuf; char path[PATH_MAX]; + size_t pathlen; - snprintf(path, PATH_MAX, "%s%s", handle->root, filestr); + pathlen = snprintf(path, PATH_MAX, "%s%s", handle->root, filestr); /* stat the file - if it exists, do some checks */ if(_alpm_lstat(path, &lsbuf) != 0) { @@ -486,10 +492,10 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, /* if we made it to here, we want all subsequent path comparisons to * not include the trailing slash. This allows things like file -> * directory replacements. */ - path[strlen(path) - 1] = '\0'; + path[pathlen - 1] = '\0'; } - relative_path = path + strlen(handle->root); + relative_path = path + rootlen; /* Check remove list (will we remove the conflicting local file?) */ for(k = remove; k && !resolved_conflict; k = k->next) { @@ -542,9 +548,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, * components can be safely checked as all directories are "unowned". */ if(!resolved_conflict && dbpkg && !S_ISLNK(lsbuf.st_mode)) { char *rpath = calloc(PATH_MAX, sizeof(char)); - const char *relative_rpath; if(realpath(path, rpath)) { - relative_rpath = rpath + strlen(handle->root); + const char *relative_rpath = rpath + rootlen; if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) { _alpm_log(handle, ALPM_LOG_DEBUG, "package contained the resolved realpath\n"); diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 8b7471fd..a129d8b0 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -1,7 +1,7 @@ /* * conflict.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 8688a3cd..8bbdc903 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -1,7 +1,7 @@ /* * db.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -22,8 +22,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -45,7 +43,7 @@ */ /** Register a sync database of packages. */ -alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle, +alpm_db_t SYMEXPORT *alpm_register_syncdb(alpm_handle_t *handle, const char *treename, alpm_siglevel_t level) { /* Sanity checks */ @@ -70,7 +68,7 @@ void _alpm_db_unregister(alpm_db_t *db) } /** Unregister all package databases. */ -int SYMEXPORT alpm_db_unregister_all(alpm_handle_t *handle) +int SYMEXPORT alpm_unregister_all_syncdbs(alpm_handle_t *handle) { alpm_list_t *i; alpm_db_t *db; @@ -263,7 +261,7 @@ alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(alpm_db_t *db) } /** Get a group entry from a package database. */ -alpm_group_t SYMEXPORT *alpm_db_readgroup(alpm_db_t *db, const char *name) +alpm_group_t SYMEXPORT *alpm_db_get_group(alpm_db_t *db, const char *name) { ASSERT(db != NULL, return NULL); db->handle->pm_errno = 0; @@ -291,32 +289,6 @@ alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles) return _alpm_db_search(db, needles); } -/** Set install reason for a package in db. */ -int SYMEXPORT alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg, - alpm_pkgreason_t reason) -{ - CHECK_HANDLE(handle, return -1); - ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); - ASSERT(pkg->origin == PKG_FROM_LOCALDB, - RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); - ASSERT(pkg->origin_data.db == handle->db_local, - RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); - - _alpm_log(handle, ALPM_LOG_DEBUG, - "setting install reason %u for %s\n", reason, pkg->name); - if(alpm_pkg_get_reason(pkg) == reason) { - /* we are done */ - return 0; - } - /* set reason (in pkgcache) */ - pkg->reason = reason; - /* write DESC */ - if(_alpm_local_db_write(handle->db_local, pkg, INFRQ_DESC)) { - RET_ERR(handle, ALPM_ERR_DB_WRITE, -1); - } - - return 0; -} /** @} */ diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 224bfbeb..94659b77 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -1,7 +1,7 @@ /* * db.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -22,8 +22,6 @@ #ifndef _ALPM_DB_H #define _ALPM_DB_H -#include <time.h> - /* libarchive */ #include <archive.h> #include <archive_entry.h> diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 6315a851..26ae5d5d 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -1,7 +1,7 @@ /* * delta.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2007-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <string.h> #include <stdint.h> /* intmax_t */ @@ -266,7 +264,8 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg) { ASSERT(pkg != NULL, return NULL); - return find_unused(pkg->deltas, pkg->filename, pkg->size * MAX_DELTA_RATIO); + return find_unused(pkg->deltas, pkg->filename, + pkg->size * pkg->handle->deltaratio); } /** @} */ @@ -275,51 +274,54 @@ alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg) * This function assumes that the string is in the correct format. * This format is as follows: * $deltafile $deltamd5 $deltasize $oldfile $newfile + * @param handle the context handle * @param line the string to parse * @return A pointer to the new alpm_delta_t object */ -/* TODO this does not really belong here, but in a parsing lib */ -alpm_delta_t *_alpm_delta_parse(char *line) +alpm_delta_t *_alpm_delta_parse(alpm_handle_t *handle, const char *line) { alpm_delta_t *delta; - char *tmp = line, *tmp2; - regex_t reg; - - regcomp(®, - "^[^[:space:]]* [[:xdigit:]]{32} [[:digit:]]*" - " [^[:space:]]* [^[:space:]]*$", - REG_EXTENDED | REG_NOSUB | REG_NEWLINE); - if(regexec(®, line, 0, 0, 0) != 0) { + const int num_matches = 6; + size_t len; + regmatch_t pmatch[num_matches]; + char filesize[32]; + + /* this is so we only have to compile the pattern once */ + if(!handle->delta_regex_compiled) { + /* $deltafile $deltamd5 $deltasize $oldfile $newfile*/ + regcomp(&handle->delta_regex, + "^([^[:space:]]+) ([[:xdigit:]]{32}) ([[:digit:]]+)" + " ([^[:space:]]+) ([^[:space:]]+)$", + REG_EXTENDED | REG_NEWLINE); + handle->delta_regex_compiled = 1; + } + + if(regexec(&handle->delta_regex, line, num_matches, pmatch, 0) != 0) { /* delta line is invalid, return NULL */ - regfree(®); return NULL; } - regfree(®); CALLOC(delta, 1, sizeof(alpm_delta_t), return NULL); - tmp2 = tmp; - tmp = strchr(tmp, ' '); - *(tmp++) = '\0'; - STRDUP(delta->delta, tmp2, return NULL); + /* start at index 1 -- match 0 is the entire match */ + len = pmatch[1].rm_eo - pmatch[1].rm_so; + STRNDUP(delta->delta, &line[pmatch[1].rm_so], len, return NULL); - tmp2 = tmp; - tmp = strchr(tmp, ' '); - *(tmp++) = '\0'; - STRDUP(delta->delta_md5, tmp2, return NULL); + len = pmatch[2].rm_eo - pmatch[2].rm_so; + STRNDUP(delta->delta_md5, &line[pmatch[2].rm_so], len, return NULL); - tmp2 = tmp; - tmp = strchr(tmp, ' '); - *(tmp++) = '\0'; - delta->delta_size = _alpm_strtoofft(tmp2); + len = pmatch[3].rm_eo - pmatch[3].rm_so; + if(len < sizeof(filesize)) { + strncpy(filesize, &line[pmatch[3].rm_so], len); + filesize[len] = '\0'; + delta->delta_size = _alpm_strtoofft(filesize); + } - tmp2 = tmp; - tmp = strchr(tmp, ' '); - *(tmp++) = '\0'; - STRDUP(delta->from, tmp2, return NULL); + len = pmatch[4].rm_eo - pmatch[4].rm_so; + STRNDUP(delta->from, &line[pmatch[4].rm_so], len, return NULL); - tmp2 = tmp; - STRDUP(delta->to, tmp2, return NULL); + len = pmatch[5].rm_eo - pmatch[5].rm_so; + STRNDUP(delta->to, &line[pmatch[5].rm_so], len, return NULL); return delta; } diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h index 05df4207..b1c89912 100644 --- a/lib/libalpm/delta.h +++ b/lib/libalpm/delta.h @@ -1,7 +1,7 @@ /* * delta.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2007-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -20,21 +20,16 @@ #ifndef _ALPM_DELTA_H #define _ALPM_DELTA_H -#include "config.h" /* ensure off_t is correct length */ - #include <sys/types.h> /* off_t */ #include "alpm.h" -alpm_delta_t *_alpm_delta_parse(char *line); +alpm_delta_t *_alpm_delta_parse(alpm_handle_t *handle, const char *line); void _alpm_delta_free(alpm_delta_t *delta); alpm_delta_t *_alpm_delta_dup(const alpm_delta_t *delta); off_t _alpm_shortest_delta_path(alpm_handle_t *handle, alpm_list_t *deltas, const char *to, alpm_list_t **path); -/* max percent of package size to download deltas */ -#define MAX_DELTA_RATIO 0.7 - #endif /* _ALPM_DELTA_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 0c0a054e..6069f5e6 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -1,7 +1,7 @@ /* * deps.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -20,8 +20,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -41,6 +39,7 @@ void _alpm_dep_free(alpm_depend_t *dep) { FREE(dep->name); FREE(dep->version); + FREE(dep->desc); FREE(dep); } @@ -204,8 +203,10 @@ alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle, static int no_dep_version(alpm_handle_t *handle) { - int flags = alpm_trans_get_flags(handle); - return flags != -1 && (flags & ALPM_TRANS_FLAG_NODEPVERSION); + if(!handle->trans) { + return 0; + } + return (handle->trans->flags & ALPM_TRANS_FLAG_NODEPVERSION); } static alpm_depend_t *filtered_depend(alpm_depend_t *dep, int nodepversion) @@ -395,7 +396,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) /* any version will satisfy the requirement */ satisfy = (provision->name_hash == dep->name_hash && strcmp(provision->name, dep->name) == 0); - } else if (provision->mod == ALPM_DEP_MOD_EQ) { + } else if(provision->mod == ALPM_DEP_MOD_EQ) { /* provision specifies a version, so try it out */ satisfy = (provision->name_hash == dep->name_hash && strcmp(provision->name, dep->name) == 0 @@ -409,7 +410,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) alpm_depend_t *_alpm_splitdep(const char *depstring) { alpm_depend_t *depend; - const char *ptr, *version; + const char *ptr, *version, *desc; size_t deplen; if(depstring == NULL) { @@ -417,7 +418,17 @@ alpm_depend_t *_alpm_splitdep(const char *depstring) } MALLOC(depend, sizeof(alpm_depend_t), return NULL); - deplen = strlen(depstring); + + /* Note the extra space in ": " to avoid matching the epoch */ + if((desc = strstr(depstring, ": ")) != NULL) { + STRDUP(depend->desc, desc + 2, return NULL); + deplen = desc - depstring; + } else { + /* no description- point desc at NULL at end of string for later use */ + depend->desc = NULL; + deplen = strlen(depstring); + desc = depstring + deplen; + } /* 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. */ @@ -442,21 +453,18 @@ alpm_depend_t *_alpm_splitdep(const char *depstring) depend->mod = ALPM_DEP_MOD_EQ; version = ptr + 1; } else { - /* no version specified, leave ptr NULL and set version to NULL */ + /* no version specified, set ptr to end of string and version to NULL */ + ptr = depstring + deplen; depend->mod = ALPM_DEP_MOD_ANY; depend->version = NULL; version = NULL; } /* copy the right parts to the right places */ - if(ptr) { - STRNDUP(depend->name, depstring, ptr - depstring, return NULL); - } else { - STRDUP(depend->name, depstring, return NULL); - } + STRNDUP(depend->name, depstring, ptr - depstring, return NULL); depend->name_hash = _alpm_hash_sdbm(depend->name); if(version) { - STRDUP(depend->version, version, return NULL); + STRNDUP(depend->version, version, desc - version, return NULL); } return depend; @@ -468,8 +476,9 @@ alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep) CALLOC(newdep, 1, sizeof(alpm_depend_t), return NULL); STRDUP(newdep->name, dep->name, return NULL); - newdep->name_hash = dep->name_hash; STRDUP(newdep->version, dep->version, return NULL); + STRDUP(newdep->desc, dep->desc, return NULL); + newdep->name_hash = dep->name_hash; newdep->mod = dep->mod; return newdep; @@ -792,7 +801,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, */ char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep) { - const char *name, *opr, *ver; + const char *name, *opr, *ver, *desc_delim, *desc; char *str; size_t len; @@ -834,12 +843,21 @@ char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep) ver = ""; } + if(dep->desc) { + desc_delim = ": "; + desc = dep->desc; + } else { + desc_delim = ""; + desc = ""; + } + /* we can always compute len and print the string like this because opr * and ver will be empty when ALPM_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; + len = strlen(name) + strlen(opr) + strlen(ver) + + strlen(desc_delim) + strlen(desc) + 1; MALLOC(str, len, return NULL); - snprintf(str, len, "%s%s%s", name, opr, ver); + snprintf(str, len, "%s%s%s%s%s", name, opr, ver, desc_delim, desc); return str; } diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index ce25bda6..c8e1bc3d 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -1,7 +1,7 @@ /* * deps.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 45908b22..ac7dab00 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -17,8 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdio.h> #include <errno.h> @@ -60,6 +58,17 @@ static int mount_point_cmp(const void *p1, const void *p2) return -strcmp(mp1->mount_dir, mp2->mount_dir); } +static void mount_point_list_free(alpm_list_t *mount_points) +{ + alpm_list_t *i; + + for(i = mount_points; i; i = i->next) { + alpm_mountpoint_t *data = i->data; + FREE(data->mount_dir); + } + FREELIST(mount_points); +} + static alpm_list_t *mount_point_list(alpm_handle_t *handle) { alpm_list_t *mount_points = NULL, *ptr; @@ -288,6 +297,72 @@ static int calculate_installed_size(alpm_handle_t *handle, return 0; } +static int check_mountpoint(alpm_handle_t *handle, alpm_mountpoint_t *mp) +{ + /* cushion is roughly min(5% capacity, 20MiB) */ + fsblkcnt_t fivepc = (mp->fsp.f_blocks / 20) + 1; + fsblkcnt_t twentymb = (20 * 1024 * 1024 / mp->fsp.f_bsize) + 1; + fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb; + blkcnt_t needed = mp->max_blocks_needed + cushion; + + _alpm_log(handle, ALPM_LOG_DEBUG, + "partition %s, needed %jd, cushion %ju, free %ju\n", + mp->mount_dir, (intmax_t)mp->max_blocks_needed, + (uintmax_t)cushion, (uintmax_t)mp->fsp.f_bfree); + if(needed >= 0 && (fsblkcnt_t)needed > mp->fsp.f_bfree) { + _alpm_log(handle, ALPM_LOG_ERROR, + _("Partition %s too full: %jd blocks needed, %jd blocks free\n"), + mp->mount_dir, (intmax_t)needed, (uintmax_t)mp->fsp.f_bfree); + return 1; + } + return 0; +} + +int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir, + size_t num_files, off_t *file_sizes) +{ + alpm_list_t *mount_points; + alpm_mountpoint_t *cachedir_mp; + size_t j; + int error = 0; + + mount_points = mount_point_list(handle); + if(mount_points == NULL) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n")); + return -1; + } + + cachedir_mp = match_mount_point(mount_points, cachedir); + if(cachedir == NULL) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine cachedir mount point %s\n"), + cachedir); + error = 1; + goto finish; + } + + /* there's no need to check for a R/O mounted filesystem here, as + * _alpm_filecache_setup will never give us a non-writable directory */ + + /* round up the size of each file to the nearest block and accumulate */ + for(j = 0; j < num_files; j++) { + cachedir_mp->max_blocks_needed += (file_sizes[j] + cachedir_mp->fsp.f_bsize + 1) / + cachedir_mp->fsp.f_bsize; + } + + if(check_mountpoint(handle, cachedir_mp)) { + error = 1; + } + +finish: + mount_point_list_free(mount_points); + + if(error) { + RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1); + } + + return 0; +} + int _alpm_check_diskspace(alpm_handle_t *handle) { alpm_list_t *mount_points, *i; @@ -356,32 +431,13 @@ int _alpm_check_diskspace(alpm_handle_t *handle) _alpm_log(handle, ALPM_LOG_ERROR, _("Partition %s is mounted read only\n"), data->mount_dir); error = 1; - } else if(data->used & USED_INSTALL) { - /* cushion is roughly min(5% capacity, 20MiB) */ - fsblkcnt_t fivepc = (data->fsp.f_blocks / 20) + 1; - fsblkcnt_t twentymb = (20 * 1024 * 1024 / data->fsp.f_bsize) + 1; - fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb; - blkcnt_t needed = data->max_blocks_needed + cushion; - - _alpm_log(handle, ALPM_LOG_DEBUG, - "partition %s, needed %jd, cushion %ju, free %ju\n", - data->mount_dir, (intmax_t)data->max_blocks_needed, - (uintmax_t)cushion, (uintmax_t)data->fsp.f_bfree); - if(needed >= 0 && (fsblkcnt_t)needed > data->fsp.f_bfree) { - _alpm_log(handle, ALPM_LOG_ERROR, - _("Partition %s too full: %jd blocks needed, %jd blocks free\n"), - data->mount_dir, (intmax_t)needed, (uintmax_t)data->fsp.f_bfree); - error = 1; - } + } else if(data->used & USED_INSTALL && check_mountpoint(handle, data)) { + error = 1; } } finish: - for(i = mount_points; i; i = i->next) { - alpm_mountpoint_t *data = i->data; - FREE(data->mount_dir); - } - FREELIST(mount_points); + mount_point_list_free(mount_points); if(error) { RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1); diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h index 5944bb17..a54aa5e3 100644 --- a/lib/libalpm/diskspace.h +++ b/lib/libalpm/diskspace.h @@ -1,7 +1,7 @@ /* * diskspace.h * - * Copyright (c) 2010-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2010-2012 Pacman Development Team <pacman-dev@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 @@ -50,6 +50,8 @@ typedef struct __alpm_mountpoint_t { } alpm_mountpoint_t; int _alpm_check_diskspace(alpm_handle_t *handle); +int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir, + size_t num_files, off_t *file_sizes); #endif /* _ALPM_DISKSPACE_H */ diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 9d982183..b3ac024c 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <errno.h> @@ -357,9 +355,7 @@ static FILE *create_tempfile(struct dload_payload *payload, const char *localpat fchmod(fd, ~(_getumask()) & 0666) || !(fp = fdopen(fd, payload->tempfile_openmode))) { unlink(randpath); - if(fd >= 0) { - close(fd); - } + CLOSE(fd); _alpm_log(payload->handle, ALPM_LOG_ERROR, _("failed to create temporary file for download\n")); return NULL; @@ -431,6 +427,10 @@ static int curl_download_internal(struct dload_payload *payload, if(localf == NULL) { localf = fopen(payload->tempfile_name, payload->tempfile_openmode); if(localf == NULL) { + handle->pm_errno = ALPM_ERR_RETRIEVE; + _alpm_log(handle, ALPM_LOG_ERROR, + _("could not open file %s: %s\n"), + payload->tempfile_name, strerror(errno)); goto cleanup; } } diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h index f5f2cd9c..e279d564 100644 --- a/lib/libalpm/dload.h +++ b/lib/libalpm/dload.h @@ -1,7 +1,7 @@ /* * dload.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -23,8 +23,6 @@ #include "alpm_list.h" #include "alpm.h" -#include <time.h> - struct dload_payload { alpm_handle_t *handle; const char *tempfile_openmode; @@ -40,6 +38,7 @@ struct dload_payload { int allow_resume; int errors_ok; int unlink_on_fail; + alpm_list_t *servers; #ifdef HAVE_LIBCURL CURLcode curlerr; /* last error produced by curl */ #endif diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index b3f56819..86b4efb2 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -1,7 +1,7 @@ /* * error.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #ifdef HAVE_LIBCURL #include <curl/curl.h> #endif @@ -29,12 +27,12 @@ #include "alpm.h" #include "handle.h" -enum _alpm_errno_t SYMEXPORT alpm_errno(alpm_handle_t *handle) +alpm_errno_t SYMEXPORT alpm_errno(alpm_handle_t *handle) { return handle->pm_errno; } -const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err) +const char SYMEXPORT *alpm_strerror(alpm_errno_t err) { switch(err) { /* System */ @@ -43,7 +41,7 @@ const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err) case ALPM_ERR_SYSTEM: return _("unexpected system error"); case ALPM_ERR_BADPERMS: - return _("insufficient privileges"); + return _("permission denied"); case ALPM_ERR_NOT_A_FILE: return _("could not find or read file"); case ALPM_ERR_NOT_A_DIR: diff --git a/lib/libalpm/graph.c b/lib/libalpm/graph.c index 3a7f24b8..69be9e30 100644 --- a/lib/libalpm/graph.c +++ b/lib/libalpm/graph.c @@ -1,7 +1,7 @@ /* * graph.c - helpful graph structure and setup/teardown methods * - * Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2007-2012 Pacman Development Team <pacman-dev@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 @@ -17,8 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include "graph.h" #include "util.h" #include "log.h" diff --git a/lib/libalpm/graph.h b/lib/libalpm/graph.h index d4d134b5..463b2cd8 100644 --- a/lib/libalpm/graph.h +++ b/lib/libalpm/graph.h @@ -1,7 +1,7 @@ /* * graph.h - helpful graph structure and setup/teardown methods * - * Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2007-2012 Pacman Development Team <pacman-dev@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 @@ -19,8 +19,6 @@ #ifndef _ALPM_GRAPH_H #define _ALPM_GRAPH_H -#include "config.h" /* ensure off_t is correct length */ - #include <sys/types.h> /* off_t */ #include "alpm_list.h" diff --git a/lib/libalpm/group.c b/lib/libalpm/group.c index 47458df2..4f4d8ce0 100644 --- a/lib/libalpm/group.c +++ b/lib/libalpm/group.c @@ -1,7 +1,7 @@ /* * group.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <string.h> diff --git a/lib/libalpm/group.h b/lib/libalpm/group.h index 078c9af7..1f776ebf 100644 --- a/lib/libalpm/group.h +++ b/lib/libalpm/group.h @@ -1,7 +1,7 @@ /* * group.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 7402be50..2db27fbf 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -1,7 +1,7 @@ /* * handle.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -20,8 +20,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <errno.h> #include <stdlib.h> #include <string.h> @@ -36,6 +34,7 @@ #include "alpm_list.h" #include "util.h" #include "log.h" +#include "delta.h" #include "trans.h" #include "alpm.h" @@ -44,6 +43,7 @@ alpm_handle_t *_alpm_handle_new(void) alpm_handle_t *handle; CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL); + handle->deltaratio = 0.0; return handle; } @@ -69,6 +69,8 @@ void _alpm_handle_free(alpm_handle_t *handle) curl_easy_cleanup(handle->curl); #endif + regfree(&handle->delta_regex); + /* free memory */ _alpm_trans_free(handle->trans); FREE(handle->root); @@ -251,10 +253,10 @@ const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) return handle->arch; } -int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle) +double SYMEXPORT alpm_option_get_deltaratio(alpm_handle_t *handle) { CHECK_HANDLE(handle, return -1); - return handle->usedelta; + return handle->deltaratio; } int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle) @@ -263,18 +265,6 @@ int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle) return handle->checkspace; } -alpm_db_t SYMEXPORT *alpm_option_get_localdb(alpm_handle_t *handle) -{ - CHECK_HANDLE(handle, return NULL); - return handle->db_local; -} - -alpm_list_t SYMEXPORT *alpm_option_get_syncdbs(alpm_handle_t *handle) -{ - CHECK_HANDLE(handle, return NULL); - return handle->dbs_sync; -} - int SYMEXPORT alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb) { CHECK_HANDLE(handle, return -1); @@ -339,7 +329,7 @@ static char *canonicalize_path(const char *path) { return new_path; } -enum _alpm_errno_t _alpm_set_directory_option(const char *value, +alpm_errno_t _alpm_set_directory_option(const char *value, char **storage, int must_exist) { struct stat st; @@ -596,10 +586,13 @@ int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch) return 0; } -int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta) +int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio) { CHECK_HANDLE(handle, return -1); - handle->usedelta = usedelta; + if(ratio < 0.0 || ratio > 2.0) { + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); + } + handle->deltaratio = ratio; return 0; } @@ -630,4 +623,16 @@ alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle return handle->siglevel; } +alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return NULL); + return handle->db_local; +} + +alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return NULL); + return handle->dbs_sync; +} + /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index 8477dcae..c0ad6686 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -1,7 +1,7 @@ /* * handle.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -22,6 +22,7 @@ #include <stdio.h> #include <sys/types.h> +#include <regex.h> #include "alpm_list.h" #include "alpm.h" @@ -86,14 +87,18 @@ struct __alpm_handle_t { alpm_list_t *ignoregroup; /* List of groups to ignore */ /* options */ - int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ char *arch; /* Architecture of packages we should allow */ - int usedelta; /* Download deltas if possible */ + double deltaratio; /* Download deltas if possible; a ratio value */ + int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ int checkspace; /* Check disk space before installing */ alpm_siglevel_t siglevel; /* Default signature verification level */ /* error code */ - enum _alpm_errno_t pm_errno; + alpm_errno_t pm_errno; + + /* for delta parsing efficiency */ + int delta_regex_compiled; + regex_t delta_regex; }; alpm_handle_t *_alpm_handle_new(void); @@ -102,7 +107,7 @@ void _alpm_handle_free(alpm_handle_t *handle); int _alpm_handle_lock(alpm_handle_t *handle); int _alpm_handle_unlock(alpm_handle_t *handle); -enum _alpm_errno_t _alpm_set_directory_option(const char *value, +alpm_errno_t _alpm_set_directory_option(const char *value, char **storage, int must_exist); #endif /* _ALPM_HANDLE_H */ diff --git a/lib/libalpm/log.c b/lib/libalpm/log.c index 692ff79c..8486716e 100644 --- a/lib/libalpm/log.c +++ b/lib/libalpm/log.c @@ -1,7 +1,7 @@ /* * log.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdio.h> #include <stdarg.h> #include <errno.h> diff --git a/lib/libalpm/log.h b/lib/libalpm/log.h index a43290d8..22c3d065 100644 --- a/lib/libalpm/log.h +++ b/lib/libalpm/log.h @@ -1,7 +1,7 @@ /* * log.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/md5.c b/lib/libalpm/md5.c index b4391a61..0d5ed9e0 100644 --- a/lib/libalpm/md5.c +++ b/lib/libalpm/md5.c @@ -33,33 +33,34 @@ * GPL. This is from version 1.0.0 of the library, and has been modified * as following, which may be helpful for future updates: * * remove "polarssl/config.h" include - * * change include from "polarssl/sha2.h" to "sha2.h" + * * change include from "polarssl/md5.h" to "md5.h" * * removal of HMAC code * * removal of SELF_TEST code - * * removal of ipad and opad from the md5_context struct in sha2.h + * * removal of ipad and opad from the md5_context struct in md5.h * * increase the size of buffer for performance reasons - * * various static changes + * * change 'unsigned long' to uint32_t */ #include <stdio.h> +#include <stdint.h> #include "md5.h" /* * 32-bit integer manipulation macros (little endian) */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ +#ifndef GET_U32_LE +#define GET_U32_LE(n,b,i) \ { \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ } #endif -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ +#ifndef PUT_U32_LE +#define PUT_U32_LE(n,b,i) \ { \ (b)[(i) ] = (unsigned char) ( (n) ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ @@ -84,24 +85,24 @@ static void md5_starts( md5_context *ctx ) static void md5_process( md5_context *ctx, const unsigned char data[64] ) { - unsigned long X[16], A, B, C, D; - - 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 ); + uint32_t X[16], A, B, C, D; + + GET_U32_LE( X[ 0], data, 0 ); + GET_U32_LE( X[ 1], data, 4 ); + GET_U32_LE( X[ 2], data, 8 ); + GET_U32_LE( X[ 3], data, 12 ); + GET_U32_LE( X[ 4], data, 16 ); + GET_U32_LE( X[ 5], data, 20 ); + GET_U32_LE( X[ 6], data, 24 ); + GET_U32_LE( X[ 7], data, 28 ); + GET_U32_LE( X[ 8], data, 32 ); + GET_U32_LE( X[ 9], data, 36 ); + GET_U32_LE( X[10], data, 40 ); + GET_U32_LE( X[11], data, 44 ); + GET_U32_LE( X[12], data, 48 ); + GET_U32_LE( X[13], data, 52 ); + GET_U32_LE( X[14], data, 56 ); + GET_U32_LE( X[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) @@ -211,7 +212,7 @@ static void md5_process( md5_context *ctx, const unsigned char data[64] ) static void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; - unsigned long left; + uint32_t left; if( ilen <= 0 ) return; @@ -219,10 +220,10 @@ static void md5_update( md5_context *ctx, const unsigned char *input, size_t ile left = ctx->total[0] & 0x3F; fill = 64 - left; - ctx->total[0] += (unsigned long) ilen; + ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; - if( ctx->total[0] < (unsigned long) ilen ) + if( ctx->total[0] < (uint32_t) ilen ) ctx->total[1]++; if( left && ilen >= fill ) @@ -262,16 +263,16 @@ static const unsigned char md5_padding[64] = */ static void md5_finish( md5_context *ctx, unsigned char output[16] ) { - unsigned long last, padn; - unsigned long high, low; + uint32_t last, padn; + uint32_t high, low; unsigned char msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_ULONG_LE( low, msglen, 0 ); - PUT_ULONG_LE( high, msglen, 4 ); + PUT_U32_LE( low, msglen, 0 ); + PUT_U32_LE( high, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); @@ -279,10 +280,10 @@ static void md5_finish( md5_context *ctx, unsigned char output[16] ) md5_update( ctx, (unsigned char *) md5_padding, padn ); md5_update( ctx, msglen, 8 ); - 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 ); + PUT_U32_LE( ctx->state[0], output, 0 ); + PUT_U32_LE( ctx->state[1], output, 4 ); + PUT_U32_LE( ctx->state[2], output, 8 ); + PUT_U32_LE( ctx->state[3], output, 12 ); } /* diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a5ff238f..a1d75a75 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -1,7 +1,7 @@ /* * package.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005, 2006 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -48,7 +46,7 @@ int SYMEXPORT alpm_pkg_free(alpm_pkg_t *pkg) ASSERT(pkg != NULL, return -1); /* Only free packages loaded in user space */ - if(pkg->origin == PKG_FROM_FILE) { + if(pkg->origin == ALPM_PKG_FROM_FILE) { _alpm_pkg_free(pkg); } @@ -64,12 +62,12 @@ int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg) ASSERT(pkg != NULL, return -1); pkg->handle->pm_errno = 0; /* We only inspect packages from sync repositories */ - ASSERT(pkg->origin == PKG_FROM_SYNCDB, + ASSERT(pkg->origin == ALPM_PKG_FROM_SYNCDB, RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); fpath = _alpm_filecache_find(pkg->handle, pkg->filename); - retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_CSUM_MD5); + retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_PKG_VALIDATION_MD5SUM); if(retval == 0) { return 0; @@ -87,12 +85,13 @@ int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg) * populated package structures. */ static const char *_pkg_get_desc(alpm_pkg_t *pkg) { return pkg->desc; } static const char *_pkg_get_url(alpm_pkg_t *pkg) { return pkg->url; } -static time_t _pkg_get_builddate(alpm_pkg_t *pkg) { return pkg->builddate; } -static time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; } +static alpm_time_t _pkg_get_builddate(alpm_pkg_t *pkg) { return pkg->builddate; } +static alpm_time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; } static const char *_pkg_get_packager(alpm_pkg_t *pkg) { return pkg->packager; } static const char *_pkg_get_arch(alpm_pkg_t *pkg) { return pkg->arch; } static off_t _pkg_get_isize(alpm_pkg_t *pkg) { return pkg->isize; } -static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; } +static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; } +static alpm_pkgvalidation_t _pkg_get_validation(alpm_pkg_t *pkg) { return pkg->validation; } static int _pkg_has_scriptlet(alpm_pkg_t *pkg) { return pkg->scriptlet; } static alpm_list_t *_pkg_get_licenses(alpm_pkg_t *pkg) { return pkg->licenses; } @@ -136,6 +135,7 @@ struct pkg_operations default_pkg_ops = { .get_arch = _pkg_get_arch, .get_isize = _pkg_get_isize, .get_reason = _pkg_get_reason, + .get_validation = _pkg_get_validation, .has_scriptlet = _pkg_has_scriptlet, .get_licenses = _pkg_get_licenses, @@ -200,14 +200,14 @@ const char SYMEXPORT *alpm_pkg_get_url(alpm_pkg_t *pkg) return pkg->ops->get_url(pkg); } -time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg) +alpm_time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg) { ASSERT(pkg != NULL, return -1); pkg->handle->pm_errno = 0; return pkg->ops->get_builddate(pkg); } -time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg) +alpm_time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg) { ASSERT(pkg != NULL, return -1); pkg->handle->pm_errno = 0; @@ -270,6 +270,13 @@ alpm_pkgreason_t SYMEXPORT alpm_pkg_get_reason(alpm_pkg_t *pkg) return pkg->ops->get_reason(pkg); } +alpm_pkgvalidation_t SYMEXPORT alpm_pkg_get_validation(alpm_pkg_t *pkg) +{ + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; + return pkg->ops->get_validation(pkg); +} + alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(alpm_pkg_t *pkg) { ASSERT(pkg != NULL, return NULL); @@ -344,7 +351,7 @@ alpm_db_t SYMEXPORT *alpm_pkg_get_db(alpm_pkg_t *pkg) { /* Sanity checks */ ASSERT(pkg != NULL, return NULL); - ASSERT(pkg->origin != PKG_FROM_FILE, return NULL); + ASSERT(pkg->origin != ALPM_PKG_FROM_FILE, return NULL); pkg->handle->pm_errno = 0; return pkg->origin_data.db; @@ -411,7 +418,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg) ASSERT(pkg != NULL, return NULL); pkg->handle->pm_errno = 0; - if(pkg->origin == PKG_FROM_FILE) { + if(pkg->origin == ALPM_PKG_FROM_FILE) { /* The sane option; search locally for things that require this. */ find_requiredby(pkg, pkg->handle->db_local, &reqs); } else { @@ -461,6 +468,15 @@ alpm_pkg_t *_alpm_pkg_new(void) return pkg; } +static alpm_list_t *list_depdup(alpm_list_t *old) +{ + alpm_list_t *i, *new = NULL; + for(i = old; i; i = i->next) { + new = alpm_list_add(new, _alpm_dep_dup(i->data)); + } + return new; +} + /** * Duplicate a package data struct. * @param pkg the package to duplicate @@ -509,10 +525,19 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr) newpkg->reason = pkg->reason; newpkg->licenses = alpm_list_strdup(pkg->licenses); - for(i = pkg->replaces; i; i = i->next) { - newpkg->replaces = alpm_list_add(newpkg->replaces, _alpm_dep_dup(i->data)); - } + newpkg->replaces = list_depdup(pkg->replaces); newpkg->groups = alpm_list_strdup(pkg->groups); + for(i = pkg->backup; i; i = i->next) { + newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data)); + } + newpkg->depends = list_depdup(pkg->depends); + newpkg->optdepends = list_depdup(pkg->optdepends); + newpkg->conflicts = list_depdup(pkg->conflicts); + newpkg->provides = list_depdup(pkg->provides); + for(i = pkg->deltas; i; i = i->next) { + newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data)); + } + if(pkg->files.count) { size_t filenum; size_t len = sizeof(alpm_file_t) * pkg->files.count; @@ -525,27 +550,11 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr) } newpkg->files.count = pkg->files.count; } - for(i = pkg->backup; i; i = i->next) { - newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data)); - } - for(i = pkg->depends; i; i = i->next) { - newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data)); - } - newpkg->optdepends = alpm_list_strdup(pkg->optdepends); - for(i = pkg->conflicts; i; i = i->next) { - newpkg->conflicts = alpm_list_add(newpkg->conflicts, _alpm_dep_dup(i->data)); - } - for(i = pkg->provides; i; i = i->next) { - newpkg->provides = alpm_list_add(newpkg->provides, _alpm_dep_dup(i->data)); - } - for(i = pkg->deltas; i; i = i->next) { - newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data)); - } /* internal */ newpkg->infolevel = pkg->infolevel; newpkg->origin = pkg->origin; - if(newpkg->origin == PKG_FROM_FILE) { + if(newpkg->origin == ALPM_PKG_FROM_FILE) { newpkg->origin_data.file = strdup(pkg->origin_data.file); } else { newpkg->origin_data.db = pkg->origin_data.db; @@ -561,6 +570,12 @@ cleanup: RET_ERR(pkg->handle, ALPM_ERR_MEMORY, -1); } +static void free_deplist(alpm_list_t *deps) +{ + alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free(deps); +} + void _alpm_pkg_free(alpm_pkg_t *pkg) { if(pkg == NULL) { @@ -579,8 +594,7 @@ void _alpm_pkg_free(alpm_pkg_t *pkg) FREE(pkg->arch); FREELIST(pkg->licenses); - alpm_list_free_inner(pkg->replaces, (alpm_list_fn_free)_alpm_dep_free); - alpm_list_free(pkg->replaces); + free_deplist(pkg->replaces); FREELIST(pkg->groups); if(pkg->files.count) { size_t i; @@ -591,27 +605,24 @@ void _alpm_pkg_free(alpm_pkg_t *pkg) } alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free); alpm_list_free(pkg->backup); - alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free); - alpm_list_free(pkg->depends); - FREELIST(pkg->optdepends); - alpm_list_free_inner(pkg->conflicts, (alpm_list_fn_free)_alpm_dep_free); - alpm_list_free(pkg->conflicts); - alpm_list_free_inner(pkg->provides, (alpm_list_fn_free)_alpm_dep_free); - alpm_list_free(pkg->provides); + free_deplist(pkg->depends); + free_deplist(pkg->optdepends); + free_deplist(pkg->conflicts); + free_deplist(pkg->provides); alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free); alpm_list_free(pkg->deltas); alpm_list_free(pkg->delta_path); alpm_list_free(pkg->removes); - if(pkg->origin == PKG_FROM_FILE) { + if(pkg->origin == ALPM_PKG_FROM_FILE) { FREE(pkg->origin_data.file); } FREE(pkg); } /* This function should be used when removing a target from upgrade/sync target list - * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed. - * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed, + * Case 1: If pkg is a loaded package file (ALPM_PKG_FROM_FILE), it will be freed. + * Case 2: If pkg is a pkgcache entry (ALPM_PKG_FROM_CACHE), it won't be freed, * only the transaction specific fields of pkg will be freed. */ void _alpm_pkg_free_trans(alpm_pkg_t *pkg) @@ -620,7 +631,7 @@ void _alpm_pkg_free_trans(alpm_pkg_t *pkg) return; } - if(pkg->origin == PKG_FROM_FILE) { + if(pkg->origin == ALPM_PKG_FROM_FILE) { _alpm_pkg_free(pkg); return; } @@ -690,14 +701,14 @@ int _alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg) alpm_list_t *groups = NULL; /* first see if the package is ignored */ - if(alpm_list_find_str(handle->ignorepkg, pkg->name)) { + if(alpm_list_find(handle->ignorepkg, pkg->name, _alpm_fnmatch)) { return 1; } /* next see if the package is in a group that is ignored */ - for(groups = handle->ignoregroup; groups; groups = groups->next) { + for(groups = alpm_pkg_get_groups(pkg); groups; groups = groups->next) { char *grp = groups->data; - if(alpm_list_find_str(alpm_pkg_get_groups(pkg), grp)) { + if(alpm_list_find(handle->ignoregroup, grp, _alpm_fnmatch)) { return 1; } } diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index eff7d898..be779b46 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -1,7 +1,7 @@ /* * package.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org> @@ -24,10 +24,7 @@ #ifndef _ALPM_PACKAGE_H #define _ALPM_PACKAGE_H -#include "config.h" /* ensure off_t is correct length */ - #include <sys/types.h> /* off_t */ -#include <time.h> /* time_t */ #include "alpm.h" #include "backup.h" @@ -44,12 +41,13 @@ struct pkg_operations { const char *(*get_desc) (alpm_pkg_t *); const char *(*get_url) (alpm_pkg_t *); - time_t (*get_builddate) (alpm_pkg_t *); - time_t (*get_installdate) (alpm_pkg_t *); + alpm_time_t (*get_builddate) (alpm_pkg_t *); + alpm_time_t (*get_installdate) (alpm_pkg_t *); const char *(*get_packager) (alpm_pkg_t *); const char *(*get_arch) (alpm_pkg_t *); off_t (*get_isize) (alpm_pkg_t *); alpm_pkgreason_t (*get_reason) (alpm_pkg_t *); + alpm_pkgvalidation_t (*get_validation) (alpm_pkg_t *); int (*has_scriptlet) (alpm_pkg_t *); alpm_list_t *(*get_licenses) (alpm_pkg_t *); @@ -89,8 +87,8 @@ struct __alpm_pkg_t { char *base64_sig; char *arch; - time_t builddate; - time_t installdate; + alpm_time_t builddate; + alpm_time_t installdate; off_t size; off_t isize; @@ -99,6 +97,7 @@ struct __alpm_pkg_t { int scriptlet; alpm_pkgreason_t reason; + alpm_pkgvalidation_t validation; alpm_dbinfrq_t infolevel; alpm_pkgfrom_t origin; /* origin == PKG_FROM_FILE, use pkg->origin_data.file @@ -136,7 +135,7 @@ void _alpm_pkg_free_trans(alpm_pkg_t *pkg); int _alpm_pkg_validate_internal(alpm_handle_t *handle, const char *pkgfile, alpm_pkg_t *syncpkg, alpm_siglevel_t level, - alpm_siglist_t **sigdata); + alpm_siglist_t **sigdata, alpm_pkgvalidation_t *validation); alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, int full); diff --git a/lib/libalpm/pkghash.c b/lib/libalpm/pkghash.c index 963ba25e..7b388004 100644 --- a/lib/libalpm/pkghash.c +++ b/lib/libalpm/pkghash.c @@ -1,7 +1,7 @@ /* * pkghash.c * - * Copyright (c) 2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2011-2012 Pacman Development Team <pacman-dev@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 @@ -26,42 +26,51 @@ * * The maximum table size is the last prime under 1,000,000. That is * more than an order of magnitude greater than the number of packages - * in any Linux distribution. + * in any Linux distribution, and well under UINT_MAX. */ -static const size_t prime_list[] = +static const unsigned int prime_list[] = { - 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul, 37ul, 41ul, 43ul, 47ul, - 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul, 83ul, 89ul, 97ul, 103ul, - 109ul, 113ul, 127ul, 137ul, 139ul, 149ul, 157ul, 167ul, 179ul, 193ul, - 199ul, 211ul, 227ul, 241ul, 257ul, 277ul, 293ul, 313ul, 337ul, 359ul, - 383ul, 409ul, 439ul, 467ul, 503ul, 541ul, 577ul, 619ul, 661ul, 709ul, - 761ul, 823ul, 887ul, 953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, - 1493ul, 1613ul, 1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, - 2753ul, 2971ul, 3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, - 5087ul, 5503ul, 5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, - 9497ul, 10273ul, 11113ul, 12011ul, 12983ul, 14033ul, 15173ul, - 16411ul, 17749ul, 19183ul, 20753ul, 22447ul, 24281ul, 26267ul, - 28411ul, 30727ul, 33223ul, 35933ul, 38873ul, 42043ul, 45481ul, - 49201ul, 53201ul, 57557ul, 62233ul, 67307ul, 72817ul, 78779ul, - 85229ul, 92203ul, 99733ul, 107897ul, 116731ul, 126271ul, 136607ul, - 147793ul, 159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul, - 256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul, 410857ul, - 444487ul, 480881ul, 520241ul, 562841ul, 608903ul, 658753ul, 712697ul, - 771049ul, 834181ul, 902483ul, 976369ul + 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u, 41u, 43u, 47u, + 53u, 59u, 61u, 67u, 71u, 73u, 79u, 83u, 89u, 97u, 103u, + 109u, 113u, 127u, 137u, 139u, 149u, 157u, 167u, 179u, 193u, + 199u, 211u, 227u, 241u, 257u, 277u, 293u, 313u, 337u, 359u, + 383u, 409u, 439u, 467u, 503u, 541u, 577u, 619u, 661u, 709u, + 761u, 823u, 887u, 953u, 1031u, 1109u, 1193u, 1289u, 1381u, + 1493u, 1613u, 1741u, 1879u, 2029u, 2179u, 2357u, 2549u, + 2753u, 2971u, 3209u, 3469u, 3739u, 4027u, 4349u, 4703u, + 5087u, 5503u, 5953u, 6427u, 6949u, 7517u, 8123u, 8783u, + 9497u, 10273u, 11113u, 12011u, 12983u, 14033u, 15173u, + 16411u, 17749u, 19183u, 20753u, 22447u, 24281u, 26267u, + 28411u, 30727u, 33223u, 35933u, 38873u, 42043u, 45481u, + 49201u, 53201u, 57557u, 62233u, 67307u, 72817u, 78779u, + 85229u, 92203u, 99733u, 107897u, 116731u, 126271u, 136607u, + 147793u, 159871u, 172933u, 187091u, 202409u, 218971u, 236897u, + 256279u, 277261u, 299951u, 324503u, 351061u, 379787u, 410857u, + 444487u, 480881u, 520241u, 562841u, 608903u, 658753u, 712697u, + 771049u, 834181u, 902483u, 976369u }; -/* Allocate a hash table with at least "size" buckets */ -alpm_pkghash_t *_alpm_pkghash_create(size_t size) +/* How far forward do we look when linear probing for a spot? */ +static const unsigned int stride = 1; +/* What is the maximum load percentage of our hash table? */ +static const double max_hash_load = 0.68; +/* Initial load percentage given a certain size */ +static const double initial_hash_load = 0.58; + +/* Allocate a hash table with space for at least "size" elements */ +alpm_pkghash_t *_alpm_pkghash_create(unsigned int size) { alpm_pkghash_t *hash = NULL; - size_t i, loopsize; + unsigned int i, loopsize; CALLOC(hash, 1, sizeof(alpm_pkghash_t), return NULL); + size = size / initial_hash_load + 1; loopsize = sizeof(prime_list) / sizeof(*prime_list); for(i = 0; i < loopsize; i++) { if(prime_list[i] > size) { hash->buckets = prime_list[i]; + hash->limit = hash->buckets * max_hash_load; break; } } @@ -78,15 +87,19 @@ alpm_pkghash_t *_alpm_pkghash_create(size_t size) return hash; } -static size_t get_hash_position(unsigned long name_hash, alpm_pkghash_t *hash) +static unsigned int get_hash_position(unsigned long name_hash, + alpm_pkghash_t *hash) { - size_t position; + unsigned int position; position = name_hash % hash->buckets; /* collision resolution using open addressing with linear probing */ while(hash->hash_table[position] != NULL) { - position = (position + 1) % hash->buckets; + position += stride; + while(position >= hash->buckets) { + position -= hash->buckets; + } } return position; @@ -96,7 +109,7 @@ static size_t get_hash_position(unsigned long name_hash, alpm_pkghash_t *hash) static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash) { alpm_pkghash_t *newhash; - size_t newsize, position, i; + unsigned int newsize, i; /* Hash tables will need resized in two cases: * - adding packages to the local database @@ -129,8 +142,7 @@ static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash) for(i = 0; i < oldhash->buckets; i++) { if(oldhash->hash_table[i] != NULL) { alpm_pkg_t *package = oldhash->hash_table[i]->data; - - position = get_hash_position(package->name_hash, newhash); + unsigned int position = get_hash_position(package->name_hash, newhash); newhash->hash_table[position] = oldhash->hash_table[i]; oldhash->hash_table[i] = NULL; @@ -144,16 +156,17 @@ static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash) return newhash; } -static alpm_pkghash_t *pkghash_add_pkg(alpm_pkghash_t *hash, alpm_pkg_t *pkg, int sorted) +static alpm_pkghash_t *pkghash_add_pkg(alpm_pkghash_t *hash, alpm_pkg_t *pkg, + int sorted) { alpm_list_t *ptr; - size_t position; + unsigned int position; if(pkg == NULL || hash == NULL) { return hash; } - if((hash->entries + 1) / MAX_HASH_LOAD > hash->buckets) { + if(hash->entries >= hash->limit) { hash = rehash(hash); } @@ -189,7 +202,8 @@ alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg) return pkghash_add_pkg(hash, pkg, 1); } -static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end) +static unsigned int move_one_entry(alpm_pkghash_t *hash, + unsigned int start, unsigned int end) { /* Iterate backwards from 'end' to 'start', seeing if any of the items * would hash to 'start'. If we find one, we move it there and break. If @@ -201,7 +215,7 @@ static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end) while(end != start) { alpm_list_t *i = hash->hash_table[end]; alpm_pkg_t *info = i->data; - size_t new_position = get_hash_position(info->name_hash, hash); + unsigned int new_position = get_hash_position(info->name_hash, hash); if(new_position == start) { hash->hash_table[start] = i; @@ -212,7 +226,7 @@ static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end) /* the odd math ensures we are always positive, e.g. * e.g. (0 - 1) % 47 == -1 * e.g. (47 + 0 - 1) % 47 == 46 */ - end = (hash->buckets + end - 1) % hash->buckets; + end = (hash->buckets + end - stride) % hash->buckets; } return end; } @@ -230,7 +244,7 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, alpm_pkg_t **data) { alpm_list_t *i; - size_t position; + unsigned int position; if(data) { *data = NULL; @@ -246,7 +260,7 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, if(info->name_hash == pkg->name_hash && strcmp(info->name, pkg->name) == 0) { - size_t stop, prev; + unsigned int stop, prev; /* remove from list and hash */ hash->list = alpm_list_remove_item(hash->list, i); @@ -260,11 +274,17 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, /* Potentially move entries following removed entry to keep open * addressing collision resolution working. We start by finding the * next null bucket to know how far we have to look. */ - stop = (position + 1) % hash->buckets; + stop = position + stride; + while(stop >= hash->buckets) { + stop -= hash->buckets; + } while(hash->hash_table[stop] != NULL && stop != position) { - stop = (stop + 1) % hash->buckets; + stop += stride; + while(stop >= hash->buckets) { + stop -= hash->buckets; + } } - stop = (hash->buckets + stop - 1) % hash->buckets; + stop = (hash->buckets + stop - stride) % hash->buckets; /* We now search backwards from stop to position. If we find an * item that now hashes to position, we will move it, and then try @@ -277,7 +297,10 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, return hash; } - position = (position + 1) % hash->buckets; + position += stride; + while(position >= hash->buckets) { + position -= hash->buckets; + } } return hash; @@ -285,8 +308,8 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, void _alpm_pkghash_free(alpm_pkghash_t *hash) { - size_t i; if(hash != NULL) { + unsigned int i; for(i = 0; i < hash->buckets; i++) { free(hash->hash_table[i]); } @@ -299,7 +322,7 @@ alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name) { alpm_list_t *lp; unsigned long name_hash; - size_t position; + unsigned int position; if(name == NULL || hash == NULL) { return NULL; @@ -316,7 +339,10 @@ alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name) return info; } - position = (position + 1) % hash->buckets; + position += stride; + while(position >= hash->buckets) { + position -= hash->buckets; + } } return NULL; diff --git a/lib/libalpm/pkghash.h b/lib/libalpm/pkghash.h index edd500e9..a2c39c7f 100644 --- a/lib/libalpm/pkghash.h +++ b/lib/libalpm/pkghash.h @@ -1,7 +1,7 @@ /* * pkghash.h * - * Copyright (c) 2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2011-2012 Pacman Development Team <pacman-dev@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 @@ -35,17 +35,19 @@ struct __alpm_pkghash_t { /** data held by the hash table */ alpm_list_t **hash_table; - /** number of buckets in hash table */ - size_t buckets; - /** number of entries in hash table */ - size_t entries; /** head node of the hash table data in normal list format */ alpm_list_t *list; + /** number of buckets in hash table */ + unsigned int buckets; + /** number of entries in hash table */ + unsigned int entries; + /** max number of entries before a resize is needed */ + unsigned int limit; }; typedef struct __alpm_pkghash_t alpm_pkghash_t; -alpm_pkghash_t *_alpm_pkghash_create(size_t size); +alpm_pkghash_t *_alpm_pkghash_create(unsigned int size); alpm_pkghash_t *_alpm_pkghash_add(alpm_pkghash_t *hash, alpm_pkg_t *pkg); alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg); @@ -55,6 +57,4 @@ void _alpm_pkghash_free(alpm_pkghash_t *hash); alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name); -#define MAX_HASH_LOAD 0.7 - #endif /* _ALPM_PKGHASH_H */ diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index cc9e289d..469ce9bb 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -22,8 +22,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <errno.h> #include <string.h> @@ -216,7 +214,7 @@ static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file, { char filepath[PATH_MAX]; - if(alpm_list_find_str(skip_remove, file->name)) { + if(alpm_list_find(skip_remove, file->name, _alpm_fnmatch)) { /* return success because we will never actually remove this file */ return 1; } @@ -239,8 +237,9 @@ static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file, /* Helper function for iterating through a package's file and deleting them * Used by _alpm_remove_commit. */ -static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, - const alpm_file_t *fileobj, alpm_list_t *skip_remove, int nosave) +static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *oldpkg, + alpm_pkg_t *newpkg, const alpm_file_t *fileobj, alpm_list_t *skip_remove, + int nosave) { struct stat buf; char file[PATH_MAX]; @@ -250,7 +249,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, /* check the remove skip list before removing the file. * see the big comment block in db_find_fileconflicts() for an * explanation. */ - if(alpm_list_find_str(skip_remove, fileobj->name)) { + if(alpm_list_find(skip_remove, fileobj->name, _alpm_fnmatch)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n", file); return 1; @@ -274,6 +273,10 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, } else if(files < 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "keeping directory %s (could not count files)\n", file); + } else if(newpkg && _alpm_filelist_contains(alpm_pkg_get_files(newpkg), + fileobj->name)) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "keeping directory %s (in new package)\n", file); } else { /* one last check- does any other package own this file? */ alpm_list_t *local, *local_pkgs; @@ -285,7 +288,8 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, /* we duplicated the package when we put it in the removal list, so we * so we can't use direct pointer comparison here. */ - if(_alpm_pkg_cmp(info, local_pkg) == 0) { + if(oldpkg->name_hash == local_pkg->name_hash + && strcmp(oldpkg->name, local_pkg->name) == 0) { continue; } filelist = alpm_pkg_get_files(local_pkg); @@ -308,7 +312,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, } } else { /* if the file needs backup and has been modified, back it up to .pacsave */ - alpm_backup_t *backup = _alpm_needbackup(fileobj->name, info); + alpm_backup_t *backup = _alpm_needbackup(fileobj->name, oldpkg); if(backup) { if(nosave) { _alpm_log(handle, ALPM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); @@ -350,38 +354,15 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, return 0; } -int _alpm_remove_single_package(alpm_handle_t *handle, +static int remove_package_files(alpm_handle_t *handle, alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg, size_t targ_count, size_t pkg_count) { alpm_list_t *skip_remove; - size_t filenum = 0, position = 0; - const char *pkgname = oldpkg->name; - const char *pkgver = oldpkg->version; alpm_filelist_t *filelist; size_t i; - - if(newpkg) { - _alpm_log(handle, ALPM_LOG_DEBUG, "removing old package first (%s-%s)\n", - pkgname, pkgver); - } else { - EVENT(handle, ALPM_EVENT_REMOVE_START, oldpkg, NULL); - _alpm_log(handle, ALPM_LOG_DEBUG, "removing package %s-%s\n", - pkgname, pkgver); - - /* run the pre-remove scriptlet if it exists */ - if(alpm_pkg_has_scriptlet(oldpkg) && - !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { - char *scriptlet = _alpm_local_db_pkgpath(handle->db_local, - oldpkg, "install"); - _alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0); - free(scriptlet); - } - } - - if(handle->trans->flags & ALPM_TRANS_FLAG_DBONLY) { - goto db; - } + int err = 0; + int nosave = handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE; if(newpkg) { alpm_filelist_t *newfiles; @@ -412,54 +393,89 @@ int _alpm_remove_single_package(alpm_handle_t *handle, alpm_file_t *file = filelist->files + i; if(!can_remove_file(handle, file, skip_remove)) { _alpm_log(handle, ALPM_LOG_DEBUG, - "not removing package '%s', can't remove all files\n", pkgname); + "not removing package '%s', can't remove all files\n", + oldpkg->name); + FREELIST(skip_remove); RET_ERR(handle, ALPM_ERR_PKG_CANT_REMOVE, -1); } - filenum++; } - _alpm_log(handle, ALPM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); + _alpm_log(handle, ALPM_LOG_DEBUG, "removing %zd files\n", filelist->count); if(!newpkg) { /* init progress bar, but only on true remove transactions */ - PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, 0, + PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name, 0, pkg_count, targ_count); } /* iterate through the list backwards, unlinking files */ for(i = filelist->count; i > 0; i--) { alpm_file_t *file = filelist->files + i - 1; - int percent; - /* TODO: check return code and handle accordingly */ - unlink_file(handle, oldpkg, file, skip_remove, - handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE); + if(unlink_file(handle, oldpkg, newpkg, file, skip_remove, nosave) < 0) { + err++; + } if(!newpkg) { /* update progress bar after each file */ - percent = (position * 100) / filenum; - PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, + int percent = ((filelist->count - i) * 100) / filelist->count; + PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name, percent, pkg_count, targ_count); } - position++; } FREELIST(skip_remove); if(!newpkg) { /* set progress to 100% after we finish unlinking files */ - PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, 100, + PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name, 100, pkg_count, targ_count); + } + + return err; +} - /* run the post-remove script if it exists */ +int _alpm_remove_single_package(alpm_handle_t *handle, + alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg, + size_t targ_count, size_t pkg_count) +{ + const char *pkgname = oldpkg->name; + const char *pkgver = oldpkg->version; + + if(newpkg) { + _alpm_log(handle, ALPM_LOG_DEBUG, "removing old package first (%s-%s)\n", + pkgname, pkgver); + } else { + EVENT(handle, ALPM_EVENT_REMOVE_START, oldpkg, NULL); + _alpm_log(handle, ALPM_LOG_DEBUG, "removing package %s-%s\n", + pkgname, pkgver); + + /* run the pre-remove scriptlet if it exists */ if(alpm_pkg_has_scriptlet(oldpkg) && !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { char *scriptlet = _alpm_local_db_pkgpath(handle->db_local, oldpkg, "install"); - _alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0); + _alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0); free(scriptlet); } } -db: + if(!(handle->trans->flags & ALPM_TRANS_FLAG_DBONLY)) { + /* TODO check returned errors if any */ + remove_package_files(handle, oldpkg, newpkg, targ_count, pkg_count); + } + + /* run the post-remove script if it exists */ + if(!newpkg && alpm_pkg_has_scriptlet(oldpkg) && + !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) { + char *scriptlet = _alpm_local_db_pkgpath(handle->db_local, + oldpkg, "install"); + _alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0); + free(scriptlet); + } + + if(!newpkg) { + EVENT(handle, ALPM_EVENT_REMOVE_DONE, oldpkg, NULL); + } + /* remove the package from the database */ _alpm_log(handle, ALPM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); if(_alpm_local_db_remove(handle->db_local, oldpkg) == -1) { @@ -472,11 +488,6 @@ db: pkgname); } - if(!newpkg) { - /* TODO: awesome! we're passing invalid pointers. */ - EVENT(handle, ALPM_EVENT_REMOVE_DONE, oldpkg, NULL); - } - return 0; } diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h index 251e4548..203eccb4 100644 --- a/lib/libalpm/remove.h +++ b/lib/libalpm/remove.h @@ -1,7 +1,7 @@ /* * remove.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/sha2.c b/lib/libalpm/sha2.c index 3632c131..366dc650 100644 --- a/lib/libalpm/sha2.c +++ b/lib/libalpm/sha2.c @@ -38,28 +38,29 @@ * * removal of SELF_TEST code * * removal of ipad and opad from the sha2_context struct in sha2.h * * increase the size of buffer for performance reasons - * * various static changes + * * change 'unsigned long' to uint32_t */ #include <stdio.h> +#include <stdint.h> #include "sha2.h" /* * 32-bit integer manipulation macros (big endian) */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ +#ifndef GET_U32_BE +#define GET_U32_BE(n,b,i) \ { \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ } #endif -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ +#ifndef PUT_U32_BE +#define PUT_U32_BE(n,b,i) \ { \ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ @@ -106,25 +107,25 @@ static void sha2_starts( sha2_context *ctx, int is224 ) static void sha2_process( sha2_context *ctx, const unsigned char data[64] ) { - unsigned long temp1, temp2, W[64]; - unsigned long A, B, C, D, E, F, G, H; - - GET_ULONG_BE( W[ 0], data, 0 ); - GET_ULONG_BE( W[ 1], data, 4 ); - GET_ULONG_BE( W[ 2], data, 8 ); - GET_ULONG_BE( W[ 3], data, 12 ); - GET_ULONG_BE( W[ 4], data, 16 ); - GET_ULONG_BE( W[ 5], data, 20 ); - GET_ULONG_BE( W[ 6], data, 24 ); - GET_ULONG_BE( W[ 7], data, 28 ); - GET_ULONG_BE( W[ 8], data, 32 ); - GET_ULONG_BE( W[ 9], data, 36 ); - GET_ULONG_BE( W[10], data, 40 ); - GET_ULONG_BE( W[11], data, 44 ); - GET_ULONG_BE( W[12], data, 48 ); - GET_ULONG_BE( W[13], data, 52 ); - GET_ULONG_BE( W[14], data, 56 ); - GET_ULONG_BE( W[15], data, 60 ); + uint32_t temp1, temp2, W[64]; + uint32_t A, B, C, D, E, F, G, H; + + GET_U32_BE( W[ 0], data, 0 ); + GET_U32_BE( W[ 1], data, 4 ); + GET_U32_BE( W[ 2], data, 8 ); + GET_U32_BE( W[ 3], data, 12 ); + GET_U32_BE( W[ 4], data, 16 ); + GET_U32_BE( W[ 5], data, 20 ); + GET_U32_BE( W[ 6], data, 24 ); + GET_U32_BE( W[ 7], data, 28 ); + GET_U32_BE( W[ 8], data, 32 ); + GET_U32_BE( W[ 9], data, 36 ); + GET_U32_BE( W[10], data, 40 ); + GET_U32_BE( W[11], data, 44 ); + GET_U32_BE( W[12], data, 48 ); + GET_U32_BE( W[13], data, 52 ); + GET_U32_BE( W[14], data, 56 ); + GET_U32_BE( W[15], data, 60 ); #define SHR(x,n) ((x & 0xFFFFFFFF) >> n) #define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) @@ -241,7 +242,7 @@ static void sha2_process( sha2_context *ctx, const unsigned char data[64] ) static void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; - unsigned long left; + uint32_t left; if( ilen <= 0 ) return; @@ -249,10 +250,10 @@ static void sha2_update( sha2_context *ctx, const unsigned char *input, size_t i left = ctx->total[0] & 0x3F; fill = 64 - left; - ctx->total[0] += (unsigned long) ilen; + ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; - if( ctx->total[0] < (unsigned long) ilen ) + if( ctx->total[0] < (uint32_t) ilen ) ctx->total[1]++; if( left && ilen >= fill ) @@ -292,16 +293,16 @@ static const unsigned char sha2_padding[64] = */ static void sha2_finish( sha2_context *ctx, unsigned char output[32] ) { - unsigned long last, padn; - unsigned long high, low; + uint32_t last, padn; + uint32_t high, low; unsigned char msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_ULONG_BE( high, msglen, 0 ); - PUT_ULONG_BE( low, msglen, 4 ); + PUT_U32_BE( high, msglen, 0 ); + PUT_U32_BE( low, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); @@ -309,16 +310,16 @@ static void sha2_finish( sha2_context *ctx, unsigned char output[32] ) sha2_update( ctx, (unsigned char *) sha2_padding, padn ); sha2_update( ctx, msglen, 8 ); - PUT_ULONG_BE( ctx->state[0], output, 0 ); - PUT_ULONG_BE( ctx->state[1], output, 4 ); - PUT_ULONG_BE( ctx->state[2], output, 8 ); - PUT_ULONG_BE( ctx->state[3], output, 12 ); - PUT_ULONG_BE( ctx->state[4], output, 16 ); - PUT_ULONG_BE( ctx->state[5], output, 20 ); - PUT_ULONG_BE( ctx->state[6], output, 24 ); + PUT_U32_BE( ctx->state[0], output, 0 ); + PUT_U32_BE( ctx->state[1], output, 4 ); + PUT_U32_BE( ctx->state[2], output, 8 ); + PUT_U32_BE( ctx->state[3], output, 12 ); + PUT_U32_BE( ctx->state[4], output, 16 ); + PUT_U32_BE( ctx->state[5], output, 20 ); + PUT_U32_BE( ctx->state[6], output, 24 ); if( ctx->is224 == 0 ) - PUT_ULONG_BE( ctx->state[7], output, 28 ); + PUT_U32_BE( ctx->state[7], output, 28 ); } /* diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c index fc8dd5bb..018b1cca 100644 --- a/lib/libalpm/signing.c +++ b/lib/libalpm/signing.c @@ -17,8 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -292,11 +290,34 @@ static int key_search(alpm_handle_t *handle, const char *fpr, pgpkey->email = key->uids->email; pgpkey->created = key->subkeys->timestamp; pgpkey->expires = key->subkeys->expires; - gpgme_release(ctx); - return 1; + pgpkey->length = key->subkeys->length; + pgpkey->revoked = key->subkeys->revoked; + + switch (key->subkeys->pubkey_algo) { + case GPGME_PK_RSA: + case GPGME_PK_RSA_E: + case GPGME_PK_RSA_S: + pgpkey->pubkey_algo = 'R'; + break; + + case GPGME_PK_DSA: + pgpkey->pubkey_algo = 'D'; + break; + + case GPGME_PK_ELG_E: + case GPGME_PK_ELG: + case GPGME_PK_ECDSA: + case GPGME_PK_ECDH: + pgpkey->pubkey_algo = 'E'; + break; + } + + ret = 1; error: - _alpm_log(handle, ALPM_LOG_DEBUG, "gpg error: %s\n", gpgme_strerror(err)); + if(ret != 1) { + _alpm_log(handle, ALPM_LOG_DEBUG, "gpg error: %s\n", gpgme_strerror(err)); + } free(full_fpr); gpgme_release(ctx); return ret; @@ -418,8 +439,13 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, if(!base64_sig) { sigpath = _alpm_sigpath(handle, path); - /* this will just help debugging */ - _alpm_access(handle, NULL, sigpath, R_OK); + if(_alpm_access(handle, NULL, sigpath, R_OK) != 0 + || (sigfile = fopen(sigpath, "rb")) == NULL) { + _alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n", + sigpath); + handle->pm_errno = ALPM_ERR_SIG_MISSING; + goto error; + } } /* does the file we are verifying exist? */ @@ -429,17 +455,6 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, goto error; } - /* does the sig file exist (if we didn't get the data directly)? */ - if(!base64_sig) { - sigfile = fopen(sigpath, "rb"); - if(sigfile == NULL) { - _alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n", - sigpath); - handle->pm_errno = ALPM_ERR_SIG_MISSING; - goto error; - } - } - if(init_gpgme(handle)) { /* pm_errno was set in gpgme_init() */ goto error; diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h index 315d6059..19ffef27 100644 --- a/lib/libalpm/signing.h +++ b/lib/libalpm/signing.h @@ -1,7 +1,7 @@ /* * signing.h * - * Copyright (c) 2008-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2008-2012 Pacman Development Team <pacman-dev@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 diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index e660d8e7..66f7ed17 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -1,7 +1,7 @@ /* * sync.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <sys/types.h> /* off_t */ #include <stdlib.h> #include <stdio.h> @@ -250,7 +248,7 @@ alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs, for(i = dbs; i; i = i->next) { alpm_db_t *db = i->data; - alpm_group_t *grp = alpm_db_readgroup(db, name); + alpm_group_t *grp = alpm_db_get_group(db, name); if(!grp) continue; @@ -290,7 +288,7 @@ static int compute_download_size(alpm_pkg_t *newpkg) alpm_handle_t *handle = newpkg->handle; int ret = 0; - if(newpkg->origin != PKG_FROM_SYNCDB) { + if(newpkg->origin != ALPM_PKG_FROM_SYNCDB) { newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = 0; return 0; @@ -320,13 +318,13 @@ static int compute_download_size(alpm_pkg_t *newpkg) /* tell the caller that we have a partial */ ret = 1; - } else if(handle->usedelta) { + } else if(handle->deltaratio > 0.0) { off_t dltsize; dltsize = _alpm_shortest_delta_path(handle, newpkg->deltas, newpkg->filename, &newpkg->delta_path); - if(newpkg->delta_path && (dltsize < newpkg->size * MAX_DELTA_RATIO)) { + if(newpkg->delta_path && (dltsize < newpkg->size * handle->deltaratio)) { _alpm_log(handle, ALPM_LOG_DEBUG, "using delta size\n"); size = dltsize; } else { @@ -367,7 +365,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; - from_sync += (spkg->origin == PKG_FROM_SYNCDB); + from_sync += (spkg->origin == ALPM_PKG_FROM_SYNCDB); } /* ensure all sync database are valid if we will be using them */ @@ -423,7 +421,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { int remove_unresolvable = 0; - enum _alpm_errno_t saved_err = handle->pm_errno; + alpm_errno_t saved_err = handle->pm_errno; QUESTION(handle, ALPM_QUESTION_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); if(remove_unresolvable) { @@ -695,11 +693,11 @@ static int apply_deltas(alpm_handle_t *handle) } else { /* len = cachedir len + from len + '/' + null */ len = strlen(cachedir) + strlen(d->from) + 2; - CALLOC(from, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1)); + MALLOC(from, len, RET_ERR(handle, ALPM_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(handle, ALPM_ERR_MEMORY, 1)); + MALLOC(to, len, RET_ERR(handle, ALPM_ERR_MEMORY, 1)); snprintf(to, len, "%s/%s", cachedir, d->to); /* build the patch command */ @@ -757,7 +755,7 @@ static int apply_deltas(alpm_handle_t *handle) * @return 1 if file was removed, 0 otherwise */ static int prompt_to_delete(alpm_handle_t *handle, const char *filepath, - enum _alpm_errno_t reason) + alpm_errno_t reason) { int doremove = 0; QUESTION(handle, ALPM_QUESTION_CORRUPTED_PKG, (char *)filepath, @@ -782,7 +780,7 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas) alpm_delta_t *d = i->data; char *filepath = _alpm_filecache_find(handle, d->delta); - if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_CSUM_MD5)) { + if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_PKG_VALIDATION_MD5SUM)) { errors = alpm_list_add(errors, filepath); } else { FREE(filepath); @@ -803,11 +801,96 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas) return 0; } +static struct dload_payload *build_payload(alpm_handle_t *handle, + const char *filename, size_t size, alpm_list_t *servers) +{ + struct dload_payload *payload; + + CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + STRDUP(payload->remote_name, filename, RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); + payload->max_size = size; + payload->servers = servers; + return payload; +} + +static int find_dl_candidates(alpm_db_t *repo, alpm_list_t **files, alpm_list_t **deltas) +{ + alpm_list_t *i; + alpm_handle_t *handle = repo->handle; + + for(i = handle->trans->add; i; i = i->next) { + alpm_pkg_t *spkg = i->data; + + if(spkg->origin != ALPM_PKG_FROM_FILE && repo == spkg->origin_data.db) { + alpm_list_t *delta_path = spkg->delta_path; + + if(!repo->servers) { + handle->pm_errno = ALPM_ERR_SERVER_NONE; + _alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n", + alpm_strerror(handle->pm_errno), repo->treename); + return 1; + } + + if(delta_path) { + /* using deltas */ + alpm_list_t *dlts; + for(dlts = delta_path; dlts; dlts = dlts->next) { + alpm_delta_t *delta = dlts->data; + if(delta->download_size != 0) { + struct dload_payload *payload = build_payload( + handle, delta->delta, delta->delta_size, repo->servers); + ASSERT(payload, return -1); + *files = alpm_list_add(*files, payload); + } + /* keep a list of all the delta files for md5sums */ + *deltas = alpm_list_add(*deltas, delta); + } + + } else if(spkg->download_size != 0) { + struct dload_payload *payload; + ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); + payload = build_payload(handle, spkg->filename, spkg->size, repo->servers); + ASSERT(payload, return -1); + *files = alpm_list_add(*files, payload); + } + } + } + + return 0; +} + +static int download_single_file(alpm_handle_t *handle, struct dload_payload *payload, + const char *cachedir) +{ + const alpm_list_t *server; + + payload->handle = handle; + payload->allow_resume = 1; + + for(server = payload->servers; server; server = server->next) { + const char *server_url = server->data; + size_t len; + + /* print server + filename into a buffer */ + len = strlen(server_url) + strlen(payload->remote_name) + 2; + MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); + snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name); + + if(_alpm_download(payload, cachedir, NULL) != -1) { + return 0; + } + + FREE(payload->fileurl); + payload->unlink_on_fail = 0; + } + + return -1; +} + static int download_files(alpm_handle_t *handle, alpm_list_t **deltas) { const char *cachedir; - alpm_list_t *i, *j; - alpm_list_t *files = NULL; + alpm_list_t *i, *files = NULL; int errors = 0; cachedir = _alpm_filecache_setup(handle); @@ -826,93 +909,53 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas) handle->totaldlcb(total_size); } - /* group sync records by repository and download */ for(i = handle->dbs_sync; i; i = i->next) { - alpm_db_t *current = i->data; - - for(j = handle->trans->add; j; j = j->next) { - alpm_pkg_t *spkg = j->data; - - if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { - alpm_list_t *delta_path = spkg->delta_path; - if(delta_path) { - /* using deltas */ - alpm_list_t *dlts; - for(dlts = delta_path; dlts; dlts = dlts->next) { - alpm_delta_t *delta = dlts->data; - if(delta->download_size != 0) { - struct dload_payload *dpayload; - - CALLOC(dpayload, 1, sizeof(*dpayload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - STRDUP(dpayload->remote_name, delta->delta, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - dpayload->max_size = delta->delta_size; - - files = alpm_list_add(files, dpayload); - } - /* keep a list of all the delta files for md5sums */ - *deltas = alpm_list_add(*deltas, delta); - } + errors += find_dl_candidates(i->data, &files, deltas); + } - } else if(spkg->download_size != 0) { - struct dload_payload *payload; + if(files) { + /* check for necessary disk space for download */ + if(handle->checkspace) { + off_t *file_sizes; + size_t idx, num_files; + int ret; - ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1)); - CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - STRDUP(payload->remote_name, spkg->filename, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - payload->max_size = spkg->size; + _alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space for download\n"); - files = alpm_list_add(files, payload); - } + num_files = alpm_list_count(files); + CALLOC(file_sizes, num_files, sizeof(off_t), goto finish); + for(i = files, idx = 0; i; i = i->next, idx++) { + const struct dload_payload *payload = i->data; + file_sizes[idx] = payload->max_size; } - } - if(files) { - if(!current->servers) { - handle->pm_errno = ALPM_ERR_SERVER_NONE; - _alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n", - alpm_strerror(handle->pm_errno), current->treename); + ret = _alpm_check_downloadspace(handle, cachedir, num_files, file_sizes); + free(file_sizes); + + if(ret != 0) { errors++; - continue; + goto finish; } + } - EVENT(handle, ALPM_EVENT_RETRIEVE_START, current->treename, NULL); - for(j = files; j; j = j->next) { - struct dload_payload *payload = j->data; - alpm_list_t *server; - int ret = -1; - for(server = current->servers; server; server = server->next) { - const char *server_url = server->data; - size_t len; - - /* print server + filename into a buffer */ - len = strlen(server_url) + strlen(payload->remote_name) + 2; - MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); - snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name); - payload->handle = handle; - payload->allow_resume = 1; - - ret = _alpm_download(payload, cachedir, NULL); - if(ret != -1) { - break; - } - FREE(payload->fileurl); - payload->unlink_on_fail = 0; - } - if(ret == -1) { - errors++; - _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files from %s\n"), - current->treename); - } + EVENT(handle, ALPM_EVENT_RETRIEVE_START, NULL, NULL); + for(i = files; i; i = i->next) { + if(download_single_file(handle, i->data, cachedir) == -1) { + errors++; + _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n")); } - - alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset); - FREELIST(files); } } - for(j = handle->trans->add; j; j = j->next) { - alpm_pkg_t *pkg = j->data; +finish: + if(files) { + alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset); + FREELIST(files); + } + + for(i = handle->trans->add; i; i = i->next) { + alpm_pkg_t *pkg = i->data; pkg->infolevel &= ~INFRQ_DSIZE; pkg->download_size = 0; } @@ -933,7 +976,8 @@ static int check_validity(alpm_handle_t *handle, char *path; alpm_siglist_t *siglist; alpm_siglevel_t level; - enum _alpm_errno_t error; + alpm_pkgvalidation_t validation; + alpm_errno_t error; }; size_t current = 0, current_bytes = 0; alpm_list_t *i, *errors = NULL; @@ -942,12 +986,12 @@ static int check_validity(alpm_handle_t *handle, EVENT(handle, ALPM_EVENT_INTEGRITY_START, NULL, NULL); for(i = handle->trans->add; i; i = i->next, current++) { - struct validity v = { i->data, NULL, NULL, 0, 0 }; + struct validity v = { i->data, NULL, NULL, 0, 0, 0 }; int percent = (int)(((double)current_bytes / total_bytes) * 100); PROGRESS(handle, ALPM_PROGRESS_INTEGRITY_START, "", percent, total, current); - if(v.pkg->origin == PKG_FROM_FILE) { + if(v.pkg->origin == ALPM_PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } @@ -956,7 +1000,7 @@ static int check_validity(alpm_handle_t *handle, v.level = alpm_db_get_siglevel(alpm_pkg_get_db(v.pkg)); if(_alpm_pkg_validate_internal(handle, v.path, v.pkg, - v.level, &v.siglist) == -1) { + v.level, &v.siglist, &v.validation) == -1) { v.error = handle->pm_errno; struct validity *invalid = malloc(sizeof(struct validity)); memcpy(invalid, &v, sizeof(struct validity)); @@ -965,6 +1009,7 @@ static int check_validity(alpm_handle_t *handle, alpm_siglist_cleanup(v.siglist); free(v.siglist); free(v.path); + v.pkg->validation = v.validation; } } @@ -1022,7 +1067,7 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data, PROGRESS(handle, ALPM_PROGRESS_LOAD_START, "", percent, total, current); - if(spkg->origin == PKG_FROM_FILE) { + if(spkg->origin == ALPM_PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } @@ -1044,6 +1089,8 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data, free(filepath); /* copy over the install reason */ pkgfile->reason = spkg->reason; + /* copy over validation method */ + pkgfile->validation = spkg->validation; i->data = pkgfile; /* spkg has been removed from the target list, so we can free the * sync-specific fields */ @@ -1090,7 +1137,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) * realistically if there are small and huge packages involved */ for(i = trans->add; i; i = i->next) { alpm_pkg_t *spkg = i->data; - if(spkg->origin != PKG_FROM_FILE) { + if(spkg->origin != ALPM_PKG_FROM_FILE) { total_bytes += spkg->size; } total++; @@ -1119,7 +1166,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) trans->state = STATE_COMMITING; /* fileconflict check */ - if(!(trans->flags & ALPM_TRANS_FLAG_FORCE)) { + if(!(trans->flags & (ALPM_TRANS_FLAG_FORCE|ALPM_TRANS_FLAG_DBONLY))) { EVENT(handle, ALPM_EVENT_FILECONFLICTS_START, NULL, NULL); _alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n"); @@ -1144,7 +1191,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) _alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space\n"); if(_alpm_check_diskspace(handle) == -1) { - _alpm_log(handle, ALPM_LOG_ERROR, "%s\n", _("not enough free disk space")); + _alpm_log(handle, ALPM_LOG_ERROR, _("not enough free disk space\n")); return -1; } diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index 472d1dfc..496f5258 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -1,7 +1,7 @@ /* * sync.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index cb97a4aa..4309c07e 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -1,7 +1,7 @@ /* * trans.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -21,8 +21,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -279,7 +277,7 @@ int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath, const char *script, const char *ver, const char *oldver, int is_archive) { char cmdline[PATH_MAX]; - char *argv[] = { "sh", "-c", cmdline, NULL }; + char *argv[] = { SCRIPTLET_SHELL, "-c", cmdline, NULL }; char *tmpdir, *scriptfn = NULL, *scriptpath; int retval = 0; size_t len; @@ -345,7 +343,7 @@ int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath, _alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\"\n", cmdline); - retval = _alpm_run_chroot(handle, "/bin/sh", argv); + retval = _alpm_run_chroot(handle, SCRIPTLET_SHELL, argv); cleanup: if(scriptfn && unlink(scriptfn)) { diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index ff944b09..acde9219 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -1,7 +1,7 @@ /* * trans.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 0e5e8a00..22e9e359 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -22,24 +22,17 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - -#include <stdio.h> #include <stdlib.h> -#include <stdarg.h> -#include <string.h> #include <unistd.h> #include <ctype.h> #include <dirent.h> -#include <fcntl.h> #include <time.h> #include <syslog.h> #include <errno.h> #include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> #include <sys/wait.h> #include <locale.h> /* setlocale */ +#include <fnmatch.h> /* libarchive */ #include <archive.h> @@ -62,8 +55,16 @@ #include "trans.h" #ifndef HAVE_STRSEP -/* This is a replacement for strsep which is not portable (missing on Solaris). - * Copyright (c) 2001 by François Gouget <fgouget_at_codeweavers.com> */ +/** Extracts tokens from a string. + * Replaces strset which is not portable (missing on Solaris). + * Copyright (c) 2001 by François Gouget <fgouget_at_codeweavers.com> + * Modifies str to point to the first character after the token if one is + * found, or NULL if one is not. + * @param str string containing delimited tokens to parse + * @param delim character delimiting tokens in str + * @return pointer to the first token in str if str is not NULL, NULL if + * str is NULL + */ char* strsep(char** str, const char* delims) { char* token; @@ -93,128 +94,106 @@ int _alpm_makepath(const char *path) return _alpm_makepath_mode(path, 0755); } -/* does the same thing as 'mkdir -p' */ +/** Creates a directory, including parents if needed, similar to 'mkdir -p'. + * @param path directory path to create + * @param mode permission mode for created directories + * @return 0 on success, 1 on error + */ int _alpm_makepath_mode(const char *path, mode_t mode) { - /* 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); + char *ptr, *str; + mode_t oldmask; int ret = 0; - orig = strdup(path); - incr = calloc(strlen(orig) + 1, sizeof(char)); - str = orig; - while((ptr = strsep(&str, "/"))) { - if(strlen(ptr)) { - /* 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(access(incr, F_OK)) { - if(mkdir(incr, mode)) { - ret = 1; - break; - } - } - } - } - free(orig); - free(incr); - umask(oldmask); - return ret; -} + STRDUP(str, path, return 1); -int _alpm_copyfile(const char *src, const char *dest) -{ - FILE *in, *out; - size_t len; - char *buf; - int ret = 0; + oldmask = umask(0000); - in = fopen(src, "rb"); - if(in == NULL) { - return 1; - } - out = fopen(dest, "wb"); - if(out == NULL) { - fclose(in); - return 1; - } + for(ptr = str; *ptr; ptr++) { + /* detect mid-path condition and zero length paths */ + if(*ptr != '/' || ptr == str || ptr[-1] == '/') { + continue; + } - MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, ret = 1; goto cleanup); + /* temporarily mask the end of the path */ + *ptr = '\0'; - /* do the actual file copy */ - while((len = fread(buf, 1, ALPM_BUFFER_SIZE, in))) { - size_t nwritten = 0; - nwritten = fwrite(buf, 1, len, out); - if((nwritten != len) || ferror(out)) { - ret = -1; - goto cleanup; + if(mkdir(str, mode) < 0 && errno != EEXIST) { + ret = 1; + goto done; } + + /* restore path separator */ + *ptr = '/'; } - /* chmod dest to permissions of src, as long as it is not a symlink */ - struct stat statbuf; - if(!stat(src, &statbuf)) { - if(! S_ISLNK(statbuf.st_mode)) { - fchmod(fileno(out), statbuf.st_mode); - } - } else { - /* stat was unsuccessful */ + /* end of the string. add the full path. It will already exist when the path + * passed in has a trailing slash. */ + if(mkdir(str, mode) < 0 && errno != EEXIST) { ret = 1; } -cleanup: - fclose(in); - fclose(out); - free(buf); +done: + umask(oldmask); + free(str); return ret; } -/* Trim whitespace and newlines from a string -*/ -char *_alpm_strtrim(char *str) +/** Copies a file. + * @param src file path to copy from + * @param dest file path to copy to + * @return 0 on success, 1 on error + */ +int _alpm_copyfile(const char *src, const char *dest) { - char *pch = str; + char *buf; + int in, out, ret = 1; + ssize_t nread; + struct stat st; - if(*str == '\0') { - /* string is empty, so we're done. */ - return str; + MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); + + OPEN(in, src, O_RDONLY); + do { + out = open(dest, O_WRONLY | O_CREAT, 0000); + } while(out == -1 && errno == EINTR); + if(in < 0 || out < 0) { + goto cleanup; } - while(isspace((unsigned char)*pch)) { - pch++; + if(fstat(in, &st) || fchmod(out, st.st_mode)) { + goto cleanup; } - if(pch != str) { - size_t len = strlen(pch); - if(len) { - memmove(str, pch, len + 1); - } else { - *str = '\0'; + + /* do the actual file copy */ + while((nread = read(in, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { + ssize_t nwrite = 0; + if(nread < 0) { + continue; } + do { + nwrite = write(out, buf + nwrite, nread); + if(nwrite >= 0) { + nread -= nwrite; + } else if(errno != EINTR) { + goto cleanup; + } + } while(nread > 0); } + ret = 0; - /* check if there wasn't anything but whitespace in the string. */ - if(*str == '\0') { - return str; +cleanup: + free(buf); + if(in >= 0) { + CLOSE(in); } - - pch = (str + (strlen(str) - 1)); - while(isspace((unsigned char)*pch)) { - pch--; + if(out >= 0) { + CLOSE(out); } - *++pch = '\0'; - - return str; + return ret; } -/** - * Trim trailing newline from a string (if one exists). +/** Trim trailing newlines from a string (if any exist). * @param str a single line of text * @return the length of the trimmed string */ @@ -235,9 +214,70 @@ size_t _alpm_strip_newline(char *str) /* Compression functions */ -/** - * @brief Unpack a specific file in an archive. - * +/** Open an archive for reading and perform the necessary boilerplate. + * This takes care of creating the libarchive 'archive' struct, setting up + * compression and format options, opening a file descriptor, setting up the + * buffer size, and performing a stat on the path once opened. + * On error, no file descriptor is opened, and the archive pointer returned + * will be set to NULL. + * @param handle the context handle + * @param path the path of the archive to open + * @param buf space for a stat buffer for the given path + * @param archive pointer to place the created archive object + * @param error error code to set on failure to open archive + * @return -1 on failure, >=0 file descriptor on success + */ +int _alpm_open_archive(alpm_handle_t *handle, const char *path, + struct stat *buf, struct archive **archive, alpm_errno_t error) +{ + int fd; + size_t bufsize = ALPM_BUFFER_SIZE; + errno = 0; + + if((*archive = archive_read_new()) == NULL) { + RET_ERR(handle, ALPM_ERR_LIBARCHIVE, -1); + } + + archive_read_support_compression_all(*archive); + archive_read_support_format_all(*archive); + + _alpm_log(handle, ALPM_LOG_DEBUG, "opening archive %s\n", path); + OPEN(fd, path, O_RDONLY); + if(fd < 0) { + _alpm_log(handle, ALPM_LOG_ERROR, + _("could not open file %s: %s\n"), path, strerror(errno)); + goto error; + } + + if(fstat(fd, buf) != 0) { + _alpm_log(handle, ALPM_LOG_ERROR, + _("could not stat file %s: %s\n"), path, strerror(errno)); + goto error; + } +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + if(buf->st_blksize > ALPM_BUFFER_SIZE) { + bufsize = buf->st_blksize; + } +#endif + + if(archive_read_open_fd(*archive, fd, bufsize) != ARCHIVE_OK) { + _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), + path, archive_error_string(*archive)); + goto error; + } + + return fd; + +error: + archive_read_finish(*archive); + *archive = NULL; + if(fd >= 0) { + CLOSE(fd); + } + RET_ERR(handle, error, -1); +} + +/** Unpack a specific file in an archive. * @param handle the context handle * @param archive the archive to unpack * @param prefix where to extract the files @@ -258,46 +298,33 @@ int _alpm_unpack_single(alpm_handle_t *handle, const char *archive, return ret; } -/** - * @brief Unpack a list of files in an archive. - * +/** Unpack a list of files in an archive. * @param handle the context handle - * @param archive the archive to unpack + * @param path the archive to unpack * @param prefix where to extract the files * @param list a list of files within the archive to unpack or NULL for all * @param breakfirst break after the first entry found - * * @return 0 on success, 1 on failure */ -int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, +int _alpm_unpack(alpm_handle_t *handle, const char *path, const char *prefix, alpm_list_t *list, int breakfirst) { int ret = 0; mode_t oldmask; - struct archive *_archive; + struct archive *archive; struct archive_entry *entry; - int cwdfd; - - if((_archive = archive_read_new()) == NULL) { - RET_ERR(handle, ALPM_ERR_LIBARCHIVE, 1); - } - - archive_read_support_compression_all(_archive); - archive_read_support_format_all(_archive); + struct stat buf; + int fd, cwdfd; - if(archive_read_open_filename(_archive, archive, - ALPM_BUFFER_SIZE) != ARCHIVE_OK) { - _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), archive, - archive_error_string(_archive)); - RET_ERR(handle, ALPM_ERR_PKG_OPEN, 1); + fd = _alpm_open_archive(handle, path, &buf, &archive, ALPM_ERR_PKG_OPEN); + if(fd < 0) { + return 1; } oldmask = umask(0022); /* save the cwd so we can restore it later */ - do { - cwdfd = open(".", O_RDONLY); - } while(cwdfd == -1 && errno == EINTR); + OPEN(cwdfd, ".", O_RDONLY); if(cwdfd < 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } @@ -310,19 +337,12 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, goto cleanup; } - while(archive_read_next_header(_archive, &entry) == ARCHIVE_OK) { - const struct stat *st; - const char *entryname; /* the name of the file in the archive */ + while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { + const char *entryname; + mode_t mode; - st = archive_entry_stat(entry); entryname = archive_entry_pathname(entry); - if(S_ISREG(st->st_mode)) { - archive_entry_set_perm(entry, 0644); - } else if(S_ISDIR(st->st_mode)) { - archive_entry_set_perm(entry, 0755); - } - /* If specific files were requested, skip entries that don't match. */ if(list) { char *entry_prefix = strdup(entryname); @@ -333,7 +353,7 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, char *found = alpm_list_find_str(list, entry_prefix); free(entry_prefix); if(!found) { - if(archive_read_data_skip(_archive) != ARCHIVE_OK) { + if(archive_read_data_skip(archive) != ARCHIVE_OK) { ret = 1; goto cleanup; } @@ -343,15 +363,22 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, } } + mode = archive_entry_mode(entry); + if(S_ISREG(mode)) { + archive_entry_set_perm(entry, 0644); + } else if(S_ISDIR(mode)) { + archive_entry_set_perm(entry, 0755); + } + /* Extract the archive entry. */ - int readret = archive_read_extract(_archive, entry, 0); + int readret = archive_read_extract(archive, entry, 0); if(readret == ARCHIVE_WARN) { /* operation succeeded but a non-critical error was encountered */ _alpm_log(handle, ALPM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), - entryname, archive_error_string(_archive)); + entryname, archive_error_string(archive)); } else if(readret != ARCHIVE_OK) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not extract %s (%s)\n"), - entryname, archive_error_string(_archive)); + entryname, archive_error_string(archive)); ret = 1; goto cleanup; } @@ -363,63 +390,20 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, cleanup: umask(oldmask); - archive_read_finish(_archive); + archive_read_finish(archive); + CLOSE(fd); if(cwdfd >= 0) { if(fchdir(cwdfd) != 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not restore working directory (%s)\n"), strerror(errno)); } - close(cwdfd); + CLOSE(cwdfd); } return ret; } -/* does the same thing as 'rm -rf' */ -int _alpm_rmrf(const char *path) -{ - int errflag = 0; - struct dirent *dp; - DIR *dirp; - struct stat st; - - if(_alpm_lstat(path, &st) == 0) { - if(!S_ISDIR(st.st_mode)) { - if(!unlink(path)) { - return 0; - } else { - if(errno == ENOENT) { - return 0; - } else { - return 1; - } - } - } else { - dirp = opendir(path); - if(!dirp) { - return 1; - } - for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - if(dp->d_name) { - if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) { - char name[PATH_MAX]; - sprintf(name, "%s/%s", path, dp->d_name); - errflag += _alpm_rmrf(name); - } - } - } - closedir(dirp); - if(rmdir(path)) { - errflag++; - } - } - return errflag; - } - return 0; -} - -/** - * Determine if there are files in a directory +/** Determine if there are files in a directory. * @param handle the context handle * @param path the full absolute directory path * @param full_count whether to return an exact count of files @@ -460,6 +444,13 @@ ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, return files; } +/** Write formatted message to log. + * @param handle the context handle + * @param format formatted string to write out + * @param args formatting arguments + * @return 0 or number of characters written on success, vfprintf return value + * on error + */ int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args) { int ret = 0; @@ -491,16 +482,20 @@ int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args) return ret; } -int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]) +/** Execute a command with arguments in a chroot. + * @param handle the context handle + * @param cmd command to execute + * @param argv arguments to pass to cmd + * @return 0 on success, 1 on error + */ +int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[]) { pid_t pid; int pipefd[2], cwdfd; int retval = 0; /* save the cwd so we can restore it later */ - do { - cwdfd = open(".", O_RDONLY); - } while(cwdfd == -1 && errno == EINTR); + OPEN(cwdfd, ".", O_RDONLY); if(cwdfd < 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } @@ -513,7 +508,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[] } _alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", - path, handle->root); + cmd, handle->root); /* Flush open fds before fork() to avoid cloning buffers */ fflush(NULL); @@ -534,12 +529,12 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[] if(pid == 0) { /* this code runs for the child only (the actual chroot/exec) */ - close(1); - close(2); + CLOSE(1); + CLOSE(2); while(dup2(pipefd[1], 1) == -1 && errno == EINTR); while(dup2(pipefd[1], 2) == -1 && errno == EINTR); - close(pipefd[0]); - close(pipefd[1]); + CLOSE(pipefd[0]); + CLOSE(pipefd[1]); /* use fprintf instead of _alpm_log to send output through the parent */ if(chroot(handle->root) != 0) { @@ -552,7 +547,8 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[] exit(1); } umask(0022); - execv(path, argv); + execv(cmd, argv); + /* execv only returns if there was an error */ fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno)); exit(1); } else { @@ -560,10 +556,10 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[] int status; FILE *pipe_file; - close(pipefd[1]); + CLOSE(pipefd[1]); pipe_file = fdopen(pipefd[0], "r"); if(pipe_file == NULL) { - close(pipefd[0]); + CLOSE(pipefd[0]); retval = 1; } else { while(!feof(pipe_file)) { @@ -605,12 +601,16 @@ cleanup: _alpm_log(handle, ALPM_LOG_ERROR, _("could not restore working directory (%s)\n"), strerror(errno)); } - close(cwdfd); + CLOSE(cwdfd); } return retval; } +/** Run ldconfig in a chroot. + * @param handle the context handle + * @return 0 on success, 1 on error + */ int _alpm_ldconfig(alpm_handle_t *handle) { char line[PATH_MAX]; @@ -629,8 +629,13 @@ int _alpm_ldconfig(alpm_handle_t *handle) return 0; } -/* Helper function for comparing strings using the - * alpm "compare func" signature */ +/** Helper function for comparing strings using the alpm "compare func" + * signature. + * @param s1 first string to be compared + * @param s2 second string to be compared + * @return 0 if strings are equal, positive int if first unequal character + * has a greater value in s1, negative if it has a greater value in s2 + */ int _alpm_str_cmp(const void *s1, const void *s2) { return strcmp(s1, s2); @@ -687,7 +692,7 @@ const char *_alpm_filecache_setup(alpm_handle_t *handle) } else if(!S_ISDIR(buf.st_mode)) { _alpm_log(handle, ALPM_LOG_DEBUG, "skipping cachedir, not a directory: %s\n", cachedir); - } else if(access(cachedir, W_OK) != 0) { + } else if(_alpm_access(handle, NULL, cachedir, W_OK) != 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "skipping cachedir, not writable: %s\n", cachedir); } else if(!(buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))) { @@ -739,51 +744,64 @@ int _alpm_lstat(const char *path, struct stat *buf) } #ifdef HAVE_LIBSSL +/** Compute the MD5 message digest of a file. + * @param path file path of file to compute MD5 digest of + * @param output string to hold computed MD5 digest + * @return 0 on success, 1 on file open error, 2 on file read error + */ static int md5_file(const char *path, unsigned char output[16]) { - FILE *f; - size_t n; MD5_CTX ctx; unsigned char *buf; + ssize_t n; + int fd; - CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1); + MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); - if((f = fopen(path, "rb")) == NULL) { + OPEN(fd, path, O_RDONLY); + if(fd < 0) { free(buf); return 1; } MD5_Init(&ctx); - while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) { + while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { + if(n < 0) { + continue; + } MD5_Update(&ctx, buf, n); } - MD5_Final(output, &ctx); - - memset(&ctx, 0, sizeof(MD5_CTX)); + CLOSE(fd); free(buf); - if(ferror(f) != 0) { - fclose(f); + if(n < 0) { return 2; } - fclose(f); + MD5_Final(output, &ctx); return 0; } /* third param is so we match the PolarSSL definition */ +/** Compute the SHA-224 or SHA-256 message digest of a file. + * @param path file path of file to compute SHA2 digest of + * @param output string to hold computed SHA2 digest + * @param is224 use SHA-224 instead of SHA-256 + * @return 0 on success, 1 on file open error, 2 on file read error + */ static int sha2_file(const char *path, unsigned char output[32], int is224) { - FILE *f; - size_t n; SHA256_CTX ctx; unsigned char *buf; + ssize_t n; + int fd; - CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1); + MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1); - if((f = fopen(path, "rb")) == NULL) { + OPEN(fd, path, O_RDONLY); + if(fd < 0) { free(buf); return 1; } @@ -794,7 +812,10 @@ static int sha2_file(const char *path, unsigned char output[32], int is224) SHA256_Init(&ctx); } - while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) { + while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) { + if(n < 0) { + continue; + } if(is224) { SHA224_Update(&ctx, buf, n); } else { @@ -802,24 +823,45 @@ static int sha2_file(const char *path, unsigned char output[32], int is224) } } + CLOSE(fd); + free(buf); + + if(n < 0) { + return 2; + } + if(is224) { SHA224_Final(output, &ctx); } else { SHA256_Final(output, &ctx); } + return 0; +} +#endif - memset(&ctx, 0, sizeof(SHA256_CTX)); - free(buf); +/** Create a string representing bytes in hexadecimal. + * @param bytes the bytes to represent in hexadecimal + * @param size number of bytes to consider + * @return a NULL terminated string with the hexadecimal representation of + * bytes or NULL on error. This string must be freed. + */ +static char *hex_representation(unsigned char *bytes, size_t size) +{ + static const char *hex_digits = "0123456789abcdef"; + char *str; + size_t i; - if(ferror(f) != 0) { - fclose(f); - return 2; + MALLOC(str, 2 * size + 1, return NULL); + + for (i = 0; i < size; i++) { + str[2 * i] = hex_digits[bytes[i] >> 4]; + str[2 * i + 1] = hex_digits[bytes[i] & 0x0f]; } - fclose(f); - return 0; + str[2 * size] = '\0'; + + return str; } -#endif /** Get the md5 sum of file. * @param filename name of the file @@ -829,28 +871,15 @@ static int sha2_file(const char *path, unsigned char output[32], int is224) char SYMEXPORT *alpm_compute_md5sum(const char *filename) { unsigned char output[16]; - char *md5sum; - int ret, i; ASSERT(filename != NULL, return NULL); - /* allocate 32 chars plus 1 for null */ - CALLOC(md5sum, 33, sizeof(char), return NULL); /* defined above for OpenSSL, otherwise defined in md5.h */ - ret = md5_file(filename, output); - - if(ret > 0) { - free(md5sum); + if(md5_file(filename, output) > 0) { return NULL; } - /* Convert the result to something readable */ - for (i = 0; i < 16; i++) { - /* sprintf is acceptable here because we know our output */ - sprintf(md5sum +(i * 2), "%02x", output[i]); - } - - return md5sum; + return hex_representation(output, 16); } /** Get the sha256 sum of file. @@ -861,39 +890,33 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename) char SYMEXPORT *alpm_compute_sha256sum(const char *filename) { unsigned char output[32]; - char *sha256sum; - int ret, i; ASSERT(filename != NULL, return NULL); - /* allocate 64 chars plus 1 for null */ - CALLOC(sha256sum, 65, sizeof(char), return NULL); /* defined above for OpenSSL, otherwise defined in sha2.h */ - ret = sha2_file(filename, output, 0); - - if(ret > 0) { - free(sha256sum); + if(sha2_file(filename, output, 0) > 0) { return NULL; } - /* Convert the result to something readable */ - for (i = 0; i < 32; i++) { - /* sprintf is acceptable here because we know our output */ - sprintf(sha256sum +(i * 2), "%02x", output[i]); - } - - return sha256sum; + return hex_representation(output, 32); } +/** Calculates a file's MD5 or SHA2 digest and compares it to an expected value. + * @param filepath path of the file to check + * @param expected hash value to compare against + * @param type digest type to use + * @return 0 if file matches the expected hash, 1 if they do not match, -1 on + * error + */ int _alpm_test_checksum(const char *filepath, const char *expected, - enum _alpm_csum type) + alpm_pkgvalidation_t type) { char *computed; int ret; - if(type == ALPM_CSUM_MD5) { + if(type == ALPM_PKG_VALIDATION_MD5SUM) { computed = alpm_compute_md5sum(filepath); - } else if(type == ALPM_CSUM_SHA256) { + } else if(type == ALPM_PKG_VALIDATION_SHA256SUM) { computed = alpm_compute_sha256sum(filepath); } else { return -1; @@ -912,18 +935,24 @@ int _alpm_test_checksum(const char *filepath, const char *expected, } /* Note: does NOT handle sparse files on purpose for speed. */ +/** TODO. + * Does not handle sparse files on purpose for speed. + * @param a + * @param b + * @return + */ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) { - char *i = NULL; - int64_t offset; - int done = 0; - /* ensure we start populating our line buffer at the beginning */ b->line_offset = b->line; while(1) { + size_t block_remaining; + char *eol; + /* have we processed this entire block? */ if(b->block + b->block_size == b->block_offset) { + int64_t offset; if(b->ret == ARCHIVE_EOF) { /* reached end of archive on the last read, now we are out of data */ goto cleanup; @@ -933,20 +962,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) b->ret = archive_read_data_block(a, (void *)&b->block, &b->block_size, &offset); b->block_offset = b->block; + block_remaining = b->block_size; /* error, cleanup */ if(b->ret < ARCHIVE_OK) { goto cleanup; } + } else { + block_remaining = b->block + b->block_size - b->block_offset; } - /* loop through the block looking for EOL characters */ - for(i = b->block_offset; i < (b->block + b->block_size); i++) { - /* check if read value was null or newline */ - if(*i == '\0' || *i == '\n') { - done = 1; - break; - } + /* look through the block looking for EOL characters */ + eol = memchr(b->block_offset, '\n', block_remaining); + if(!eol) { + eol = memchr(b->block_offset, '\0', block_remaining); } /* allocate our buffer, or ensure our existing one is big enough */ @@ -956,8 +985,10 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) b->line_size = b->block_size + 1; b->line_offset = b->line; } else { - size_t needed = (size_t)((b->line_offset - b->line) - + (i - b->block_offset) + 1); + /* note: we know eol > b->block_offset and b->line_offset > b->line, + * so we know the result is unsigned and can fit in size_t */ + size_t new = eol ? (size_t)(eol - b->block_offset) : block_remaining; + size_t needed = (size_t)((b->line_offset - b->line) + new + 1); if(needed > b->max_line_size) { b->ret = -ERANGE; goto cleanup; @@ -974,11 +1005,11 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) } } - if(done) { - size_t len = (size_t)(i - b->block_offset); + if(eol) { + size_t len = (size_t)(eol - b->block_offset); memcpy(b->line_offset, b->block_offset, len); b->line_offset[len] = '\0'; - b->block_offset = ++i; + b->block_offset = eol + 1; /* this is the main return point; from here you can read b->line */ return ARCHIVE_OK; } else { @@ -986,7 +1017,7 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) size_t len = (size_t)(b->block + b->block_size - b->block_offset); memcpy(b->line_offset, b->block_offset, len); b->line_offset += len; - b->block_offset = i; + b->block_offset = b->block + b->block_size; /* there was no new data, return what is left; saved ARCHIVE_EOF will be * returned on next call */ if(len == 0) { @@ -1005,6 +1036,14 @@ cleanup: } } +/** Parse a full package specifier. + * @param target package specifier to parse, such as: "pacman-4.0.1-2", + * "pacman-4.01-2/", or "pacman-4.0.1-2/desc" + * @param name to hold package name + * @param version to hold package version + * @param name_hash to hold package name hash + * @return 0 on success, -1 on error + */ int _alpm_splitname(const char *target, char **name, char **version, unsigned long *name_hash) { @@ -1057,8 +1096,7 @@ int _alpm_splitname(const char *target, char **name, char **version, return 0; } -/** - * Hash the given string to an unsigned long value. +/** Hash the given string to an unsigned long value. * This is the standard sdbm hashing algorithm. * @param str string to hash * @return the hash value of the given string @@ -1072,12 +1110,17 @@ unsigned long _alpm_hash_sdbm(const char *str) return hash; } while((c = *str++)) { - hash = c + (hash << 6) + (hash << 16) - hash; + hash = c + hash * 65599; } return hash; } +/** Convert a string to a file offset. + * This parses bare positive integers only. + * @param line string to convert + * @return off_t on success, -1 on error + */ off_t _alpm_strtoofft(const char *line) { char *end; @@ -1089,13 +1132,13 @@ off_t _alpm_strtoofft(const char *line) return (off_t)-1; } result = strtoull(line, &end, 10); - if (result == 0 && end == line) { + if(result == 0 && end == line) { /* line was not a number */ return (off_t)-1; - } else if (result == ULLONG_MAX && errno == ERANGE) { + } else if(result == ULLONG_MAX && errno == ERANGE) { /* line does not fit in unsigned long long */ return (off_t)-1; - } else if (*end) { + } else if(*end) { /* line began with a number but has junk left over at the end */ return (off_t)-1; } @@ -1103,8 +1146,16 @@ off_t _alpm_strtoofft(const char *line) return (off_t)result; } -time_t _alpm_parsedate(const char *line) +/** Parses a date into an alpm_time_t struct. + * @param line date to parse + * @return time struct on success, 0 on error + */ +alpm_time_t _alpm_parsedate(const char *line) { + char *end; + long long result; + errno = 0; + if(isalpha((unsigned char)line[0])) { /* initialize to null in case of failure */ struct tm tmp_tm; @@ -1112,13 +1163,27 @@ time_t _alpm_parsedate(const char *line) setlocale(LC_TIME, "C"); strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm); setlocale(LC_TIME, ""); - return mktime(&tmp_tm); + return (alpm_time_t)mktime(&tmp_tm); + } + + result = strtoll(line, &end, 10); + if(result == 0 && end == line) { + /* line was not a number */ + errno = EINVAL; + return 0; + } else if(errno == ERANGE) { + /* line does not fit in long long */ + return 0; + } else if(*end) { + /* line began with a number but has junk left over at the end */ + errno = EINVAL; + return 0; } - return (time_t)atol(line); + + return (alpm_time_t)result; } -/** - * Wrapper around access() which takes a dir and file argument +/** Wrapper around access() which takes a dir and file argument * separately and generates an appropriate error message. * If dir is NULL file will be treated as the whole path. * @param handle an alpm handle @@ -1127,13 +1192,12 @@ time_t _alpm_parsedate(const char *line) * @param amode access mode as described in access() * @return int value returned by access() */ - int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode) { size_t len = 0; int ret = 0; - if (dir) { + if(dir) { char *check_path; len = strlen(dir) + strlen(file) + 1; @@ -1148,19 +1212,19 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a } if(ret != 0) { - if (amode & R_OK) { + if(amode & R_OK) { _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not readable: %s\n", dir, file, strerror(errno)); } - if (amode & W_OK) { + if(amode & W_OK) { _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not writable: %s\n", dir, file, strerror(errno)); } - if (amode & X_OK) { + if(amode & X_OK) { _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not executable: %s\n", dir, file, strerror(errno)); } - if (amode == F_OK) { + if(amode == F_OK) { _alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" does not exist: %s\n", dir, file, strerror(errno)); } @@ -1168,8 +1232,25 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a return ret; } +/** Checks whether a string matches a shell wildcard pattern. + * Wrapper around fnmatch. + * @param pattern pattern to match aganist + * @param string string to check against pattern + * @return 0 if string matches pattern, non-zero if they don't match and on + * error + */ +int _alpm_fnmatch(const void *pattern, const void *string) +{ + return fnmatch(pattern, string, 0); +} + #ifndef HAVE_STRNDUP /* A quick and dirty implementation derived from glibc */ +/** Determines the length of a fixed-size string. + * @param s string to be measured + * @param max maximum number of characters to search for the string end + * @return length of s or max, whichever is smaller + */ static size_t strnlen(const char *s, size_t max) { register const char *p; @@ -1177,6 +1258,12 @@ static size_t strnlen(const char *s, size_t max) return (p - s); } +/** Copies a string. + * Returned string needs to be freed + * @param s string to be copied + * @param n maximum number of characters to copy + * @return pointer to the new string on success, NULL on error + */ char *strndup(const char *s, size_t n) { size_t len = strnlen(s, n); diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 26fa9044..e6747827 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -1,7 +1,7 @@ /* * util.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -24,8 +24,6 @@ #ifndef _ALPM_UTIL_H #define _ALPM_UTIL_H -#include "config.h" - #include "alpm_list.h" #include "alpm.h" #include "package.h" /* alpm_pkg_t */ @@ -35,11 +33,13 @@ #include <string.h> #include <stdarg.h> #include <stddef.h> /* size_t */ -#include <time.h> +#include <sys/types.h> #include <sys/stat.h> /* struct stat */ -#include <archive.h> /* struct archive */ #include <math.h> /* fabs */ #include <float.h> /* DBL_EPSILON */ +#include <fcntl.h> /* open, close */ + +#include <archive.h> /* struct archive */ #ifdef ENABLE_NLS #include <libintl.h> /* here so it doesn't need to be included elsewhere */ @@ -51,8 +51,8 @@ #define ALLOC_FAIL(s) do { fprintf(stderr, "alloc failure: could not allocate %zd bytes\n", s); } while(0) -#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 MALLOC(p, s, action) do { p = malloc(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(l * 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 STRNDUP(r, s, l, action) do { if(s != NULL) { r = strndup(s, l); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } else { r = NULL; } } while(0) @@ -82,6 +82,13 @@ #define ALPM_BUFFER_SIZE 8192 #endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#define OPEN(fd, path, flags) do { fd = open(path, flags | O_BINARY); } while(fd == -1 && errno == EINTR) +#define CLOSE(fd) do { int ret; do { ret = close(fd); } while(ret == -1 && errno == EINTR); } while(0) + /** * Used as a buffer/state holder for _alpm_archive_fgets(). */ @@ -98,39 +105,37 @@ struct archive_read_buffer { int ret; }; -enum _alpm_csum { - ALPM_CSUM_MD5, - ALPM_CSUM_SHA256, -}; - 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); -char *_alpm_strtrim(char *str); size_t _alpm_strip_newline(char *str); + +int _alpm_open_archive(alpm_handle_t *handle, const char *path, + struct stat *buf, struct archive **archive, alpm_errno_t error); int _alpm_unpack_single(alpm_handle_t *handle, const char *archive, const char *prefix, const char *filename); int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix, alpm_list_t *list, int breakfirst); -int _alpm_rmrf(const char *path); + ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, int full_count); int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args); -int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]); +int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[]); int _alpm_ldconfig(alpm_handle_t *handle); int _alpm_str_cmp(const void *s1, const void *s2); char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename); const char *_alpm_filecache_setup(alpm_handle_t *handle); int _alpm_lstat(const char *path, struct stat *buf); -int _alpm_test_checksum(const char *filepath, const char *expected, enum _alpm_csum type); +int _alpm_test_checksum(const char *filepath, const char *expected, alpm_pkgvalidation_t type); int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b); int _alpm_splitname(const char *target, char **name, char **version, unsigned long *name_hash); unsigned long _alpm_hash_sdbm(const char *str); off_t _alpm_strtoofft(const char *line); -time_t _alpm_parsedate(const char *line); +alpm_time_t _alpm_parsedate(const char *line); int _alpm_raw_cmp(const char *first, const char *second); int _alpm_raw_ncmp(const char *first, const char *second, size_t max); int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode); +int _alpm_fnmatch(const void *pattern, const void *string); #ifndef HAVE_STRSEP char *strsep(char **, const char *); diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c index 6b65a413..269a7016 100644 --- a/lib/libalpm/version.c +++ b/lib/libalpm/version.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@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 @@ -15,8 +15,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <string.h> #include <ctype.h> diff --git a/m4/gpgme.m4 b/m4/gpgme.m4 new file mode 100644 index 00000000..44bf43cb --- /dev/null +++ b/m4/gpgme.m4 @@ -0,0 +1,307 @@ +# gpgme.m4 - autoconf macro to detect GPGME. +# Copyright (C) 2002, 2003, 2004 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +AC_DEFUN([_AM_PATH_GPGME_CONFIG], +[ AC_ARG_WITH(gpgme-prefix, + AC_HELP_STRING([--with-gpgme-prefix=PFX], + [prefix where GPGME is installed (optional)]), + gpgme_config_prefix="$withval", gpgme_config_prefix="") + if test "x$gpgme_config_prefix" != x ; then + GPGME_CONFIG="$gpgme_config_prefix/bin/gpgme-config" + fi + AC_PATH_PROG(GPGME_CONFIG, gpgme-config, no) + + if test "$GPGME_CONFIG" != "no" ; then + gpgme_version=`$GPGME_CONFIG --version` + fi + gpgme_version_major=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + gpgme_version_minor=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + gpgme_version_micro=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` +]) + +dnl AM_PATH_GPGME([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme and define GPGME_CFLAGS and GPGME_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_CFLAGS=`$GPGME_CONFIG --cflags` + GPGME_LIBS=`$GPGME_CONFIG --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_CFLAGS="" + GPGME_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_CFLAGS) + AC_SUBST(GPGME_LIBS) +]) + +dnl AM_PATH_GPGME_PTH([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme and define GPGME_PTH_CFLAGS and GPGME_PTH_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME_PTH], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME Pth - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + if `$GPGME_CONFIG --thread=pth 2> /dev/null` ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_PTH_CFLAGS=`$GPGME_CONFIG --thread=pth --cflags` + GPGME_PTH_LIBS=`$GPGME_CONFIG --thread=pth --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_PTH_CFLAGS="" + GPGME_PTH_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_PTH_CFLAGS) + AC_SUBST(GPGME_PTH_LIBS) +]) + +dnl AM_PATH_GPGME_PTHREAD([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme and define GPGME_PTHREAD_CFLAGS +dnl and GPGME_PTHREAD_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME_PTHREAD], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME pthread - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + if `$GPGME_CONFIG --thread=pthread 2> /dev/null` ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --thread=pthread --cflags` + GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --thread=pthread --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_PTHREAD_CFLAGS="" + GPGME_PTHREAD_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_PTHREAD_CFLAGS) + AC_SUBST(GPGME_PTHREAD_LIBS) +]) + + +dnl AM_PATH_GPGME_GLIB([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme-glib and define GPGME_GLIB_CFLAGS and GPGME_GLIB_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME_GLIB], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_GLIB_CFLAGS=`$GPGME_CONFIG --glib --cflags` + GPGME_GLIB_LIBS=`$GPGME_CONFIG --glib --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_GLIB_CFLAGS="" + GPGME_GLIB_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_GLIB_CFLAGS) + AC_SUBST(GPGME_GLIB_LIBS) +]) + diff --git a/scripts/Makefile.am b/scripts/Makefile.am index d89fd306..328fbff2 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -60,14 +60,10 @@ edit = sed \ ## All the scripts depend on Makefile so that they are rebuilt when the ## prefix etc. changes. Use chmod -w to prevent people from editing the ## wrong file by accident. -# two 'test' lines- make sure we can handle both sh and py type scripts -# third 'test' line- make sure one of the two checks succeeded $(OURSCRIPTS): Makefile - @echo ' ' GEN $@; - @$(RM) $@ - @test -f $(srcdir)/$@.sh.in && m4 -P -I $(srcdir) $(srcdir)/$@.sh.in | $(edit) >$@ - @chmod +x $@ - @chmod a-w $@ + $(AM_V_at)$(RM) $@ + $(AM_V_GEN)test -f $(srcdir)/$@.sh.in && m4 -P -I $(srcdir) $(srcdir)/$@.sh.in | $(edit) >$@ + $(AM_V_at)chmod +x,a-w $@ makepkg: \ $(srcdir)/makepkg.sh.in \ diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index eeb7ede1..1fa4819a 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -39,10 +39,10 @@ export COMMAND_MODE='legacy' # Ensure CDPATH doesn't screw with our cd calls unset CDPATH -myver='@PACKAGE_VERSION@' -confdir='@sysconfdir@' -BUILDSCRIPT='@BUILDSCRIPT@' -startdir="$PWD" +declare -r myver='@PACKAGE_VERSION@' +declare -r confdir='@sysconfdir@' +declare -r BUILDSCRIPT='@BUILDSCRIPT@' +declare -r startdir="$PWD" packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx') other_options=('ccache' 'distcc' 'buildflags' 'makeflags') @@ -211,7 +211,7 @@ get_filepath() { return 1 fi - echo "$file" + printf "%s\n" "$file" } # Print 'source not found' error message and exit makepkg @@ -226,13 +226,13 @@ get_filename() { # if a filename is specified, use it local filename="${1%%::*}" # if it is just an URL, we only keep the last component - echo "${filename##*/}" + printf "%s\n" "${filename##*/}" } # extract the URL from a source entry get_url() { # strip an eventual filename - echo "${1#*::}" + printf "%s\n" "${1#*::}" } ## @@ -242,9 +242,9 @@ get_url() { get_full_version() { if [[ -z $1 ]]; then if [[ $epoch ]] && (( ! $epoch )); then - echo $pkgver-$pkgrel + printf "%s\n" "$pkgver-$pkgrel" else - echo $epoch:$pkgver-$pkgrel + printf "%s\n" "$epoch:$pkgver-$pkgrel" fi else for i in pkgver pkgrel epoch; do @@ -253,9 +253,9 @@ get_full_version() { [[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\" done if (( ! $epoch_override )); then - echo $pkgver_override-$pkgrel_override + printf "%s\n" "$pkgver_override-$pkgrel_override" else - echo $epoch_override:$pkgver_override-$pkgrel_override + printf "%s\n" "$epoch_override:$pkgver_override-$pkgrel_override" fi fi } @@ -272,14 +272,14 @@ get_full_version() { check_option() { local ret=$(in_opt_array "$1" ${options[@]}) if [[ $ret != '?' ]]; then - echo $ret + printf "%s\n" "$ret" return fi # fall back to makepkg.conf options ret=$(in_opt_array "$1" ${OPTIONS[@]}) if [[ $ret != '?' ]]; then - echo $ret + printf "%s\n" "$ret" return fi @@ -311,7 +311,7 @@ in_opt_array() { local opt for opt in "$@"; do - if [[ $opt = $needle ]]; then + if [[ $opt = "$needle" ]]; then echo 'y' # Enabled return elif [[ $opt = "!$needle" ]]; then @@ -333,15 +333,15 @@ in_array() { local needle=$1; shift local item for item in "$@"; do - [[ $item = $needle ]] && return 0 # Found + [[ $item = "$needle" ]] && return 0 # Found done return 1 # Not Found } -source_has_signatures(){ +source_has_signatures() { local file for file in "${source[@]}"; do - if [[ $file = *.@(sig?(n)|asc) ]]; then + if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then return 0 fi done @@ -357,7 +357,7 @@ get_downloadclient() { local i for i in "${DLAGENTS[@]}"; do local handler="${i%%::*}" - if [[ $proto = $handler ]]; then + if [[ $proto = "$handler" ]]; then local agent="${i##*::}" break fi @@ -379,7 +379,7 @@ get_downloadclient() { exit 1 # $E_MISSING_PROGRAM fi - echo "$agent" + printf "%s\n" "$agent" } download_file() { @@ -420,18 +420,18 @@ download_file() { run_pacman() { local cmd if [[ ! $1 = -@(T|Qq) ]]; then - printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@" + cmd=("$PACMAN" $PACMAN_OPTS "$@") else - printf -v cmd "%q " "$PACMAN" "$@" + cmd=("$PACMAN" "$@") fi if (( ! ASROOT )) && [[ ! $1 = -@(T|Qq) ]]; then if type -p sudo >/dev/null; then - cmd="sudo $cmd" + cmd=(sudo "${cmd[@]}") else - cmd="su root -c '$cmd'" + cmd=(su root -c "$(printf '%q ' "${cmd[@]}")") fi fi - eval "$cmd" + "${cmd[@]}" } check_deps() { @@ -446,7 +446,7 @@ check_deps() { set -E if (( ret == 127 )); then #unresolved deps - echo "$pmout" + printf "%s\n" "$pmout" elif (( ret )); then error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout" return "$ret" @@ -557,7 +557,7 @@ download_sources() { local url=$(get_url "$netfile") # if we get here, check to make sure it was a URL, else fail - if [[ $file = $url ]]; then + if [[ $file = "$url" ]]; then error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file" exit 1 # $E_MISSING_FILE fi @@ -594,9 +594,9 @@ get_integlist() { done if (( ${#integlist[@]} > 0 )); then - echo ${integlist[@]} + printf "%s\n" "${integlist[@]}" else - echo ${INTEGRITY_CHECK[@]} + printf "%s\n" "${INTEGRITY_CHECK[@]}" fi } @@ -627,7 +627,7 @@ generate_checksums() { local ct=0 local numsrc=${#source[@]} - echo -n "${integ}sums=(" + printf "%s" "${integ}sums=(" local i local indent='' @@ -641,8 +641,8 @@ generate_checksums() { file="$(get_filepath "$netfile")" || missing_source_file "$netfile" local sum="$(openssl dgst -${integ} "$file")" sum=${sum##* } - (( ct )) && echo -n "$indent" - echo -n "'$sum'" + (( ct )) && printf "%s" "$indent" + printf "%s" "'$sum'" ct=$(($ct+1)) (( $ct < $numsrc )) && echo done @@ -668,7 +668,7 @@ check_checksums() { for file in "${source[@]}"; do local found=1 file="$(get_filename "$file")" - echo -n " $file ... " >&2 + printf "%s" " $file ... " >&2 if ! file="$(get_filepath "$file")"; then printf -- "$(gettext "NOT FOUND")\n" >&2 @@ -677,14 +677,18 @@ check_checksums() { fi if (( $found )) ; then - local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}") - local realsum="$(openssl dgst -${integ} "$file")" - realsum="${realsum##* }" - if [[ $expectedsum = $realsum ]]; then - printf -- "$(gettext "Passed")\n" >&2 + if [[ ${integrity_sums[$idx]} = 'SKIP' ]]; then + echo "$(gettext "Skipped")" >&2 else - printf -- "$(gettext "FAILED")\n" >&2 - errors=1 + local expectedsum=$(tr '[:upper:]' '[:lower:]' <<< "${integrity_sums[$idx]}") + local realsum="$(openssl dgst -${integ} "$file")" + realsum="${realsum##* }" + if [[ $expectedsum = "$realsum" ]]; then + printf -- "$(gettext "Passed")\n" >&2 + else + printf -- "$(gettext "FAILED")\n" >&2 + errors=1 + fi fi fi @@ -838,10 +842,10 @@ extract_sources() { local ret=0 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd" - if [[ $cmd = bsdtar ]]; then + if [[ $cmd = "bsdtar" ]]; then $cmd -xf "$file" || ret=$? else - rm -f "${file%.*}" + rm -f -- "${file%.*}" $cmd -dcf "$file" > "${file%.*}" || ret=$? fi if (( ret )); then @@ -870,6 +874,14 @@ error_function() { exit 2 # $E_BUILD_FAILED } +cd_safe() { + if ! cd "$1"; then + error "$(gettext "Failed to change to directory %s")" "$1" + plain "$(gettext "Aborting...")" + exit 1 + fi +} + run_function() { if [[ -z $1 ]]; then return 1 @@ -887,7 +899,7 @@ run_function() { fi msg "$(gettext "Starting %s()...")" "$pkgfunc" - cd "$srcdir" + cd_safe "$srcdir" # ensure all necessary build variables are exported export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST @@ -965,19 +977,19 @@ run_package() { } tidy_install() { - cd "$pkgdir" + cd_safe "$pkgdir" msg "$(gettext "Tidying install...")" if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then msg2 "$(gettext "Removing doc files...")" - rm -rf ${DOC_DIRS[@]} + rm -rf -- ${DOC_DIRS[@]} fi if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then msg2 "$(gettext "Purging unwanted files...")" local pt for pt in "${PURGE_TARGETS[@]}"; do - if [[ ${pt} = ${pt//\/} ]]; then + if [[ ${pt} = "${pt//\/}" ]]; then find . -type f -name "${pt}" -exec rm -f -- '{}' \; else rm -f ${pt} @@ -997,7 +1009,7 @@ tidy_install() { find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null | while read link ; do rm -f "$link" "${link}.gz" - ln -s "${file}.gz" "${link}.gz" + ln -s -- "${file}.gz" "${link}.gz" done # check file still exists (potentially already compressed due to hardlink) @@ -1021,7 +1033,7 @@ tidy_install() { done fi - if [[ $(check_option strip) = y ]]; then + if [[ $(check_option strip) = "y" ]]; then msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")" # make sure library stripping variables are defined to prevent excess stripping [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S" @@ -1078,8 +1090,8 @@ find_libdepends() { if in_array "${soname}" ${depends[@]}; then if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then # libfoo.so=1-64 - echo "${soname}=${soversion}-${soarch}" - libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}") + printf "%s" "${soname}=${soversion}-${soarch}" + libdepends+=("${soname}=${soversion}-${soarch}") fi fi done @@ -1087,30 +1099,62 @@ find_libdepends() { } find_libprovides() { - local libprovides - find "$pkgdir" -type f -name \*.so\* | while read filename - do - # check if we really have a shared object - if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then - # 64 - soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') - # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1 - sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') - [ -z "$sofile" ] && sofile="${filename##*/}" - - # extract the library name: libfoo.so - soname="${sofile%%\.so\.*}.so" - # extract the major version: 1 - soversion="${sofile##*\.so\.}" - if in_array "${soname}" ${provides[@]}; then - if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then - # libfoo.so=1-64 - echo "${soname}=${soversion}-${soarch}" - libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}") + local libprovides missing + for p in "${provides[@]}"; do + missing=0 + case "$p" in + *.so) + IFS=$'\n' read -rd '' -a filename < <(find "$pkgdir" -type f -name $p\*) + if [[ $filename ]]; then + # packages may provide multiple versions of the same library + for fn in "${filename[@]}"; do + # check if we really have a shared object + if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then + # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1) + local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') + if [[ -z "$sofile" ]]; then + warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p" + libprovides+=("$p") + continue + fi + + # get the library architecture (32 or 64 bit) + local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + + # extract the library major version + local soversion="${sofile##*\.so\.}" + + libprovides+=("${p}=${soversion}-${soarch}") + else + warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" + libprovides+=("$p") + fi + done + else + libprovides+=("$p") + missing=1 fi - fi - fi + ;; + *) + libprovides+=("$p") + ;; + esac + + if (( missing )); then + warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p" + fi done + + printf '%s\n' "${libprovides[@]}" +} + +check_license() { + # TODO maybe remove this at some point + # warn if license array is not present or empty + if [[ -z $license ]]; then + warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT" + plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')" + fi } write_pkginfo() { @@ -1135,29 +1179,31 @@ write_pkginfo() { echo "# using $(fakeroot -v)" fi echo "# $(LC_ALL=C date -u)" - echo "pkgname = $1" + printf "pkgname = %s\n" "$1" (( SPLITPKG )) && echo pkgbase = $pkgbase echo "pkgver = $(get_full_version)" - echo "pkgdesc = $pkgdesc" - echo "url = $url" - echo "builddate = $builddate" - echo "packager = $packager" - echo "size = $size" - echo "arch = $PKGARCH" + printf "pkgdesc = %s\n" "$pkgdesc" + printf "url = %s\n" "$url" + printf "builddate = %s\n" "$builddate" + printf "packager = %s\n" "$packager" + printf "size = %s\n" "$size" + printf "arch = %s\n" "$PKGARCH" [[ $license ]] && printf "license = %s\n" "${license[@]}" [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}" [[ $groups ]] && printf "group = %s\n" "${groups[@]}" [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }" [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}" + + IFS=$'\n' read -rd '' -a provides < <(find_libprovides) + [[ $provides ]] && printf "provides = %s\n" "${provides[@]}" + [[ $backup ]] && printf "backup = %s\n" "${backup[@]}" - local it - libprovides=$(find_libprovides) - libdepends=$(find_libdepends) - provides=("${provides[@]}" ${libprovides}) - depends=("${depends[@]}" ${libdepends}) + local it + IFS=$'\n' read -rd '' -a libdepends < <(find_libdepends) + depends+=("${libdepends[@]}") for it in "${depends[@]}"; do if [[ $it = *.so ]]; then @@ -1169,45 +1215,26 @@ write_pkginfo() { return 1 fi else - echo "depend = $it" - fi - done - - for it in "${provides[@]}"; do - # ignore versionless entires (those come from the PKGBUILD) - if [[ $it = *.so ]]; then - # check if the entry has been found by find_libprovides - # if not, it's unneeded; tell the user so he can remove it - if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then - error "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$it" - return 1 - fi - else - echo "provides = $it" + printf "depend = %s\n" "$it" fi done for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then - if [[ $ret = y ]]; then - echo "makepkgopt = $it" + if [[ $ret = "y" ]]; then + printf "makepkgopt = %s\n" "$it" else - echo "makepkgopt = !$it" + printf "makepkgopt = %s\n" "!$it" fi fi done - # TODO maybe remove this at some point - # warn if license array is not present or empty - if [[ -z $license ]]; then - warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT" - plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')" - fi + check_license } check_package() { - cd "$pkgdir" + cd_safe "$pkgdir" # check existence of backup files local file @@ -1236,7 +1263,7 @@ create_package() { check_package - cd "$pkgdir" + cd_safe "$pkgdir" msg "$(gettext "Creating package...")" local nameofpkg @@ -1254,7 +1281,7 @@ create_package() { write_pkginfo $nameofpkg > .PKGINFO - local comp_files=".PKGINFO" + local comp_files=('.PKGINFO') # check for changelog/install files for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do @@ -1264,7 +1291,7 @@ create_package() { msg2 "$(gettext "Adding %s file...")" "$orig" cp "$startdir/${!orig}" "$dest" chmod 644 "$dest" - comp_files+=" $dest" + comp_files+=("$dest") fi done @@ -1286,12 +1313,12 @@ create_package() { # bsdtar's gzip compression always saves the time stamp, making one # archive created using the same command line distinct from another. # Disable bsdtar compression and use gzip -n for now. - bsdtar -cf - $comp_files * | + bsdtar -cf - "${comp_files[@]}" * | case "$PKGEXT" in - *tar.gz) gzip -c -f -n ;; - *tar.bz2) bzip2 -c -f ;; - *tar.xz) xz -c -z - ;; - *tar.Z) compress -c -f ;; + *tar.gz) ${COMPRESSGZ[@]:-gzip -c -f -n} ;; + *tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;; + *tar.xz) ${COMPRESSXZ[@]:-xz -c -z -} ;; + *tar.Z) ${COMPRESSZ[@]:-compress -c -f} ;; *tar) cat ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT"; cat ;; @@ -1351,12 +1378,14 @@ create_srcpackage() { local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)" mkdir "${srclinks}"/${pkgbase} + check_license + msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}" local file for file in "${source[@]}"; do - if [[ "$file" == $(get_filename "$file") ]] || (( SOURCEONLY == 2 )); then + if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then local absfile absfile=$(get_filepath "$file") || missing_source_file "$file" msg2 "$(gettext "Adding %s...")" "${absfile##*/}" @@ -1393,7 +1422,7 @@ create_srcpackage() { # tar it up msg2 "$(gettext "Compressing source package...")" - cd "${srclinks}" + cd_safe "${srclinks}" if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then error "$(gettext "Failed to create source package file.")" exit 1 # TODO: error code @@ -1409,7 +1438,7 @@ create_srcpackage() { warning "$(gettext "Failed to create symlink to source package file.")" fi - cd "${startdir}" + cd_safe "${startdir}" rm -rf "${srclinks}" } @@ -1473,8 +1502,8 @@ check_sanity() { awk -F'=' '$1 ~ /^[[:space:]]*pkgrel$/' "$BUILDFILE" | sed "s/[[:space:]]*#.*//" | while IFS='=' read -r _ i; do eval i=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "${i%%+([[:space:]])}")\" - if [[ $i = *[[:space:]-]* ]]; then - error "$(gettext "%s is not allowed to contain hyphens or whitespace.")" "pkgrel" + if [[ $i != +([0-9])?(.+([0-9])) ]]; then + error "$(gettext "%s must be a decimal.")" "pkgrel" return 1 fi done || ret=1 @@ -1566,7 +1595,7 @@ check_sanity() { known=0 # check if option matches a known option or its inverse for kopt in ${packaging_options[@]} ${other_options[@]}; do - if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then + if [[ ${i} = "${kopt}" || ${i} = "!${kopt}" ]]; then known=1 fi done @@ -1690,7 +1719,7 @@ devel_check() { # Do not update pkgver if --holdver is set, when building a source package, repackaging, # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w) if (( HOLDVER || SOURCEONLY || REPKG )) || - [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then + [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = "/dev/stdin" ]]; then return fi @@ -1700,66 +1729,67 @@ devel_check() { # calls to makepkg via fakeroot will explicitly pass the version # number to avoid having to determine the version number twice. # Also do a check to make sure we have the VCS tool available. - oldpkgver=$pkgver - if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then - if ! type -p darcs >/dev/null; then - warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "darcs" "darcs" - return 0 - fi - msg "$(gettext "Determining latest %s revision...")" 'darcs' - newpkgver=$(date +%Y%m%d) - elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then - if ! type -p cvs >/dev/null; then - warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "cvs" "cvs" - return 0 - fi - msg "$(gettext "Determining latest %s revision...")" 'cvs' - newpkgver=$(date +%Y%m%d) - elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then - if ! type -p git >/dev/null; then - warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "git" "git" - return 0 - fi - msg "$(gettext "Determining latest %s revision...")" 'git' - newpkgver=$(date +%Y%m%d) - elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then - if ! type -p svn >/dev/null; then - warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "svn" "svn" - return 0 - fi - msg "$(gettext "Determining latest %s revision...")" 'svn' - newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p') - elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then - if ! type -p bzr >/dev/null; then - warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "bzr" "bzr" - return 0 - fi - msg "$(gettext "Determining latest %s revision...")" 'bzr' - newpkgver=$(bzr revno ${_bzrtrunk}) - elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then - if ! type -p hg >/dev/null; then - warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "hg" "hg" - return 0 - fi - msg "$(gettext "Determining latest %s revision...")" 'hg' - if [[ -d ./src/$_hgrepo ]] ; then - cd ./src/$_hgrepo - local ret=0 - hg pull || ret=$? - if (( ! ret )); then - hg update - elif (( ret != 1 )); then - return 1 - fi - else - [[ ! -d ./src/ ]] && mkdir ./src/ - hg clone $_hgroot/$_hgrepo ./src/$_hgrepo - cd ./src/$_hgrepo - fi - newpkgver=$(hg tip --template "{rev}") - cd ../../ + local vcs=() + + [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] && vcs+=("darcs") + [[ -n ${_cvsroot} && -n ${_cvsmod} ]] && vcs+=("cvs") + [[ -n ${_gitroot} && -n ${_gitname} ]] && vcs+=("git") + [[ -n ${_svntrunk} && -n ${_svnmod} ]] && vcs+=("svn") + [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] && vcs+=("bzr") + [[ -n ${_hgroot} && -n ${_hgrepo} ]] && vcs+=("hg") + + if (( ${#vcs[@]} == 0 )); then + return + elif (( ${#vcs[@]} > 1 )); then + warning "$(gettext "Ambiguous VCS package. Cannot pick from: %s.")" "${vcs[*]}" + return 0 fi + if ! type -p "$vcs" >/dev/null; then + warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "$vcs" "$vcs" + return 0 + fi + + msg "$(gettext "Determining latest %s revision...")" "$vcs" + + case "$vcs" in + darcs) + newpkgver=$(date +%Y%m%d) + ;; + cvs) + newpkgver=$(date +%Y%m%d) + ;; + git) + newpkgver=$(date +%Y%m%d) + ;; + svn) + newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p') + ;; + bzr) + newpkgver=$(bzr revno ${_bzrtrunk}) + ;; + hg) + if pushd "./src/$_hgrepo" > /dev/null; then + local ret=0 + hg pull || ret=$? + if (( ! ret )); then + hg update + elif (( ret != 1 )); then + return 1 + fi + else + [[ ! -d ./src/ ]] && mkdir ./src/ + hg clone "$_hgroot/$_hgrepo" "./src/$_hgrepo" + if ! pushd "./src/$_hgrepo" > /dev/null; then + warning "$(gettext "An error occured while determining the hg version number.")" + return 0 + fi + fi + newpkgver=$(hg tip --template "{rev}") + popd > /dev/null + ;; + esac + if [[ -n $newpkgver ]]; then msg2 "$(gettext "Version found: %s")" "$newpkgver" fi @@ -1833,11 +1863,11 @@ canonicalize_path() { if [[ -d $path ]]; then ( - cd "$path" + cd_safe "$path" pwd -P ) else - echo "$path" + printf "%s\n" "$path" fi } @@ -1902,7 +1932,7 @@ There is NO WARRANTY, to the extent permitted by law.\n")" # determine whether we have gettext; make it a no-op if we do not if ! type -p gettext >/dev/null; then gettext() { - echo "$@" + printf "%s\n" "$@" } fi @@ -1989,6 +2019,7 @@ set -E [[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT} [[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT} [[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY} +[[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER} # default config is makepkg.conf MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} @@ -2037,8 +2068,11 @@ readonly ALL_OFF BOLD BLUE GREEN RED YELLOW BUILDDIR=${_BUILDDIR:-$BUILDDIR} BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined if [[ ! -d $BUILDDIR ]]; then - mkdir -p "$BUILDDIR" || - error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR" + if ! mkdir -p "$BUILDDIR"; then + error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR" + plain "$(gettext "Aborting...")" + exit 1 + fi chmod a-s "$BUILDDIR" fi if [[ ! -w $BUILDDIR ]]; then @@ -2046,8 +2080,6 @@ if [[ ! -w $BUILDDIR ]]; then plain "$(gettext "Aborting...")" exit 1 fi -srcdir="$BUILDDIR/src" -pkgdir="$BUILDDIR/pkg" PKGDEST=${_PKGDEST:-$PKGDEST} PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined @@ -2076,6 +2108,7 @@ fi PKGEXT=${_PKGEXT:-$PKGEXT} SRCEXT=${_SRCEXT:-$SRCEXT} GPGKEY=${_GPGKEY:-$GPGKEY} +PACKAGER=${_PACKAGER:-$PACKAGER} if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then # The '\\0' is here to prevent gettext from thinking --holdver is an option @@ -2143,10 +2176,18 @@ fi pkgbase=${pkgbase:-${pkgname[0]}} epoch=${epoch:-0} +if [[ $BUILDDIR = "$startdir" ]]; then + srcdir="$BUILDDIR/src" + pkgdir="$BUILDDIR/pkg" +else + srcdir="$BUILDDIR/$pkgbase/src" + pkgdir="$BUILDDIR/$pkgbase/pkg" +fi + if (( GENINTEG )); then mkdir -p "$srcdir" chmod a-s "$srcdir" - cd "$srcdir" + cd_safe "$srcdir" download_sources generate_checksums exit 0 # $E_OK @@ -2296,14 +2337,14 @@ if (( SOURCEONLY )); then # Get back to our src directory so we can begin with sources. mkdir -p "$srcdir" chmod a-s "$srcdir" - cd "$srcdir" + cd_safe "$srcdir" if ( (( ! SKIPCHECKSUMS )) || \ ( (( ! SKIPPGPCHECK )) && source_has_signatures ) ) || \ (( SOURCEONLY == 2 )); then download_sources fi check_source_integrity - cd "$startdir" + cd_safe "$startdir" # if we are root or if fakeroot is not enabled, then we don't use it if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then @@ -2359,7 +2400,7 @@ umask 0022 # get back to our src directory so we can begin with sources mkdir -p "$srcdir" chmod a-s "$srcdir" -cd "$srcdir" +cd_safe "$srcdir" if (( NOEXTRACT )); then warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/" @@ -2395,7 +2436,7 @@ else fi mkdir -p "$pkgdir" chmod a-s "$pkgdir" - cd "$startdir" + cd_safe "$startdir" # if we are root or if fakeroot is not enabled, then we don't use it if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then @@ -2425,7 +2466,7 @@ else devel_update (( BUILDFUNC )) && run_build (( CHECKFUNC )) && run_check - cd "$startdir" + cd_safe "$startdir" fi enter_fakeroot diff --git a/scripts/pacman-db-upgrade.sh.in b/scripts/pacman-db-upgrade.sh.in index e0a049c5..894152f6 100644 --- a/scripts/pacman-db-upgrade.sh.in +++ b/scripts/pacman-db-upgrade.sh.in @@ -23,7 +23,7 @@ export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='@localedir@' -myver='@PACKAGE_VERSION@' +declare -r myver='@PACKAGE_VERSION@' eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf) dbroot="${DBPath:-@localstatedir@/lib/pacman/}" diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index 87d7658f..288b76eb 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -24,7 +24,7 @@ export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='@localedir@' -myver="@PACKAGE_VERSION@" +declare -r myver="@PACKAGE_VERSION@" # Options ADD=0 @@ -245,8 +245,7 @@ populate_keyring() { fi # Variable used for iterating on keyrings - local key - local key_id + local keys key_id # Add keys from requested keyrings for keyring in "${KEYRINGIDS[@]}"; do @@ -262,14 +261,12 @@ populate_keyring() { local -A trusted_ids for keyring in "${KEYRINGIDS[@]}"; do if [[ -f "${KEYRING_IMPORT_DIR}/${keyring}-trusted" ]]; then - while read key; do - # skip comments; these are valid in this file - [[ $key = \#* ]] && continue - key_id="${key%%:*}" - if [[ -n ${key_id} ]]; then - # Mark this key to be lsigned - trusted_ids[$key_id]="${keyring}" - fi + while IFS=: read key_id _; do + # skip blank lines, comments; these are valid in this file + [[ -z $key_id || ${key_id:0:1} = \# ]] && continue + + # Mark this key to be lsigned + trusted_ids[$key_id]=$keyring done < "${KEYRING_IMPORT_DIR}/${keyring}-trusted" fi done @@ -294,13 +291,13 @@ populate_keyring() { local -A revoked_ids for keyring in "${KEYRINGIDS[@]}"; do if [[ -f "${KEYRING_IMPORT_DIR}/${keyring}-revoked" ]]; then - while read key; do - key_id="$("${GPG_PACMAN[@]}" --quiet --with-colons --list-key "${key}" 2>/dev/null | grep ^pub | cut -d: -f5)" - if [[ -n ${key_id} ]]; then + IFS=$'\n' read -r -d '' -a keys < "${KEYRING_IMPORT_DIR}/${keyring}-revoked" + while IFS=: read _ _ _ _ key_id _; do + if [[ -n $key_id ]]; then # Mark this key to be disabled revoked_ids[$key_id]="${keyring}" fi - done < "${KEYRING_IMPORT_DIR}/${keyring}-revoked" + done < <("${GPG_PACMAN[@]}" --quiet --with-colons --list-keys "${keys[@]}" 2>/dev/null) fi done diff --git a/scripts/pacman-optimize.sh.in b/scripts/pacman-optimize.sh.in index 8a4e7224..4a84c0bb 100644 --- a/scripts/pacman-optimize.sh.in +++ b/scripts/pacman-optimize.sh.in @@ -24,7 +24,7 @@ export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='@localedir@' -myver='@PACKAGE_VERSION@' +declare -r myver='@PACKAGE_VERSION@' eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf) dbroot="${DBPath:-@localstatedir@/lib/pacman/}" @@ -88,9 +88,8 @@ if [[ -n $1 ]]; then dbroot="$1" fi -# make sure diff is installed -if ! type diff >/dev/null 2>&1; then - die "$(gettext "diff tool was not found, please install diffutils.")" +if ! type -p openssl >/dev/null; then + die "$(gettext "Cannot find the %s binary required for verifying integrity.")" "openssl" fi if [[ ! -d $dbroot || ! -d $dbroot/local ]]; then @@ -103,8 +102,8 @@ fi # strip any trailing slash from our dbroot dbroot="${dbroot%/}" -# form the path to our lockfile location lockfile="${dbroot}/db.lck" +localdb="${dbroot}/local" # make sure pacman isn't running if [[ -f $lockfile ]]; then @@ -113,42 +112,44 @@ fi # do not let pacman run while we do this touch "$lockfile" -workdir=$(mktemp -d /tmp/pacman-optimize.XXXXXXXXXX) || +workdir=$(mktemp -d "${TMPDIR:-/tmp}/pacman-optimize.XXXXXXXXXX") || die_r "$(gettext "Can not create temp directory for database building.")\n" >&2 # step 1: sum the old db msg "$(gettext "MD5sum'ing the old database...")" -find "$dbroot" -type f | sort | xargs md5sum > "$workdir/pacsums.old" +(cd "$localdb" && find . -type f -print0 | \ + xargs -0 openssl dgst -md5 | sort > "$workdir/pacsums.old") # step 2: tar it up -msg "$(gettext "Tar'ing up %s...")" "$dbroot" -bsdtar -czf "$workdir/pacman-db.tar.gz" -C "$dbroot" ./ +msg "$(gettext "Tar'ing up %s...")" "$localdb" +bsdtar -czf "$workdir/pacman-db.tar.gz" -C "$localdb" ./ if (( $? )); then rm -rf "$workdir" - die_r "$(gettext "Tar'ing up %s failed.")" "$dbroot" + die_r "$(gettext "Tar'ing up %s failed.")" "$localdb" fi # step 3: make and sum the new db side-by-side with the old msg "$(gettext "Making and MD5sum'ing the new database...")" -mkdir "$dbroot.new" -bsdtar -xpf "$workdir/pacman-db.tar.gz" -C "$dbroot.new" +mkdir "$localdb.new" +bsdtar -xpf "$workdir/pacman-db.tar.gz" -C "$localdb.new" if (( $? )); then rm -rf "$workdir" - die_r "$(gettext "Untar'ing %s failed.")" "$dbroot" + die_r "$(gettext "Untar'ing %s failed.")" "$localdb" fi # immediate sync following extraction should get it written continuously on HDD msg "$(gettext "Syncing database to disk...")" sync -find "$dbroot.new" -type f | sort | \ - xargs md5sum | sed 's#.new##' > "$workdir/pacsums.new" +(cd "$localdb.new" && find . -type f -print0 | \ + xargs -0 openssl dgst -md5 | sort > "$workdir/pacsums.new") # step 4: compare the sums msg "$(gettext "Checking integrity...")" -diff "$workdir/pacsums.old" "$workdir/pacsums.new" >/dev/null 2>&1 -if (( $? )); then +read -ra old_dgst < <(openssl dgst -md5 < "$workdir/pacsums.old") +read -ra new_dgst < <(openssl dgst -md5 < "$workdir/pacsums.new") +if [[ ${old_dgst[@]:(-1)} != ${new_dgst[@]:(-1)} ]]; then # failed # leave our pacman-optimize tmpdir for checking to see what doesn't match up - rm -rf "$dbroot.new" + rm -rf "$localdb.new" die_r "$(gettext "Integrity check FAILED, reverting to old database.")" fi @@ -156,15 +157,15 @@ fi msg "$(gettext "Rotating database into place...")" fail=0 -mv "$dbroot" "$dbroot.old" || fail=1 -mv "$dbroot.new" "$dbroot" || fail=1 -chmod --reference="$dbroot.old" "$dbroot" || fail=1 -chown --reference="$dbroot.old" "$dbroot" || fail=1 +mv "$localdb" "$localdb.old" || fail=1 +mv "$localdb.new" "$localdb" || fail=1 +chmod --reference="$localdb.old" "$localdb" || fail=1 +chown --reference="$localdb.old" "$localdb" || fail=1 if (( fail )); then # failure with our directory shuffle - die_r "$(gettext "New database substitution failed. Check for $dbroot,\n$dbroot.old, and $dbroot.new directories.")" + die_r "$(gettext "New database substitution failed. Check for %s, %s, and %s directories.")" "$localdb" "$localdb.old" "$localdb.new" fi -rm -rf "$dbroot.old" +rm -rf "$localdb.old" # remove the lock file and our working directory with sums and tarfile rm -f "$lockfile" diff --git a/scripts/pkgdelta.sh.in b/scripts/pkgdelta.sh.in index 5fcc5be4..992c85f3 100644 --- a/scripts/pkgdelta.sh.in +++ b/scripts/pkgdelta.sh.in @@ -26,7 +26,7 @@ set -o errexit export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='@localedir@' -myver='@PACKAGE_VERSION@' +declare -r myver='@PACKAGE_VERSION@' QUIET=0 diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index 2bb9c83f..5159ea2f 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -25,8 +25,8 @@ shopt -s extglob export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='@localedir@' -myver='@PACKAGE_VERSION@' -confdir='@sysconfdir@' +declare -r myver='@PACKAGE_VERSION@' +declare -r confdir='@sysconfdir@' QUIET=0 DELTA=0 @@ -176,6 +176,11 @@ db_remove_delta() { if grep -q "$filename" $deltas; then sed -i.backup "/$filename/d" $deltas && rm -f $deltas.backup msg2 "$(gettext "Removing existing entry '%s'...")" "$filename" + # empty deltas file contains only "%DELTAS%" + if (( $(wc -l < "$deltas") == 1 )); then + msg2 "$(gettext "Removing empty deltas file ...")" + rm "$deltas" + fi return 0 fi @@ -203,7 +208,7 @@ create_signature() { gpg --detach-sign --use-agent ${SIGNWITHKEY} "$dbfile" &>/dev/null || ret=$? if (( ! ret )); then - msg2 "$(gettext "Created signature file %s.")" "${dbfile##*/}.sig" + msg2 "$(gettext "Created signature file %s.")" "${dbfile##*/.tmp.}.sig" else warning "$(gettext "Failed to sign package database.")" fi @@ -424,13 +429,8 @@ elephant() { check_repo_db() { local repodir - # ensure the path to the DB exists - if [[ "$LOCKFILE" == /* ]]; then - repodir=${LOCKFILE%/*}/ - else - repodir=$PWD/$LOCKFILE - repodir=${repodir%/*}/ - fi + # ensure the path to the DB exists; $LOCKFILE is always an absolute path + repodir=${LOCKFILE%/*}/ if [[ ! -d "$repodir" ]]; then error "$(gettext "%s does not exist or is not a directory.")" "$repodir" @@ -579,7 +579,7 @@ if [[ $cmd != "repo-add" && $cmd != "repo-remove" ]]; then exit 1 fi -tmpdir=$(mktemp -d /tmp/repo-tools.XXXXXXXXXX) || (\ +tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/repo-tools.XXXXXXXXXX") || (\ error "$(gettext "Cannot create temp directory for database building.")"; \ exit 1) mkdir $tmpdir/tree @@ -637,7 +637,11 @@ if [[ -z $REPO_DB_FILE ]]; then exit 1 fi -LOCKFILE=$REPO_DB_FILE.lck +if [[ $REPO_DB_FILE == /* ]]; then + LOCKFILE=$REPO_DB_FILE.lck +else + LOCKFILE=$PWD/$REPO_DB_FILE.lck +fi verify_repo_extension "$REPO_DB_FILE" >/dev/null check_repo_db @@ -654,37 +658,51 @@ if (( success )); then msg "$(gettext "Creating updated database file '%s'")" "$REPO_DB_FILE" TAR_OPT=$(verify_repo_extension "$REPO_DB_FILE") + # $LOCKFILE is already guaranteed to be absolute so this is safe + dirname=${LOCKFILE%/*} filename=${REPO_DB_FILE##*/} + # this ensures we create it on the same filesystem, making moves atomic + tempname="$dirname/.tmp.$filename" pushd "$tmpdir/tree" >/dev/null if ( shopt -s nullglob; files=(*); (( ${#files[*]} )) ); then - bsdtar -c${TAR_OPT}f "$tmpdir/$filename" * + bsdtar -c${TAR_OPT}f "$tempname" * else # we have no packages remaining? zip up some emptyness warning "$(gettext "No packages remain, creating empty database.")" - bsdtar -c${TAR_OPT}f "$tmpdir/$filename" -T /dev/null + bsdtar -c${TAR_OPT}f "$tempname" -T /dev/null fi popd >/dev/null - create_signature "$tmpdir/$filename" + create_signature "$tempname" - [[ -f $REPO_DB_FILE ]] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old" + # hardlink or move the previous version of the database and signature to .old + # extension as a backup measure + if [[ -f $REPO_DB_FILE ]]; then + ln -f "$REPO_DB_FILE" "$REPO_DB_FILE.old" 2>/dev/null || \ + mv -f "$REPO_DB_FILE" "$REPO_DB_FILE.old" + fi if [[ -f $REPO_DB_FILE.sig ]]; then - mv -f "$REPO_DB_FILE.sig" "$REPO_DB_FILE.old.sig" + ln -f "$REPO_DB_FILE.sig" "$REPO_DB_FILE.old.sig" 2>/dev/null || \ + mv -f "$REPO_DB_FILE.sig" "$REPO_DB_FILE.old.sig" else rm -f "$REPO_DB_FILE.old.sig" fi - [[ -f $tmpdir/$filename ]] && mv "$tmpdir/$filename" "$REPO_DB_FILE" - [[ -f $tmpdir/$filename.sig ]] && mv "$tmpdir/$filename.sig" "$REPO_DB_FILE.sig" + + # rotate the newly-created database and signature into place + mv "$tempname" "$REPO_DB_FILE" + if [[ -f $tempname.sig ]]; then + mv "$tempname.sig" "$REPO_DB_FILE.sig" + fi + dblink="${REPO_DB_FILE%.tar*}" - target=${REPO_DB_FILE##*/} rm -f "$dblink" "$dblink.sig" - ln -s "$target" "$dblink" 2>/dev/null || \ - ln "$target" "$dblink" 2>/dev/null || \ + ln -s "$filename" "$dblink" 2>/dev/null || \ + ln "$filename" "$dblink" 2>/dev/null || \ cp "$REPO_DB_FILE" "$dblink" if [[ -f "$REPO_DB_FILE.sig" ]]; then - ln -s "$target.sig" "$dblink.sig" 2>/dev/null || \ - ln "$target.sig" "$dblink.sig" 2>/dev/null || \ + ln -s "$filename.sig" "$dblink.sig" 2>/dev/null || \ + ln "$filename.sig" "$dblink.sig" 2>/dev/null || \ cp "$REPO_DB_FILE.sig" "$dblink.sig" fi else diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am index 3790bdf4..9a92fd6b 100644 --- a/src/pacman/Makefile.am +++ b/src/pacman/Makefile.am @@ -11,13 +11,15 @@ bin_PROGRAMS = pacman DEFS = -DLOCALEDIR=\"@localedir@\" \ -DCONFFILE=\"$(conffile)\" \ - -DROOTDIR=\"$(ROOTDIR)\" \ -DDBPATH=\"$(dbpath)\" \ -DGPGDIR=\"$(gpgdir)\" \ -DCACHEDIR=\"$(cachedir)\" \ -DLOGFILE=\"$(logfile)\" \ @DEFS@ -INCLUDES = -I$(top_srcdir)/lib/libalpm + +AM_CPPFLAGS = \ + -imacros $(top_builddir)/config.h \ + -I$(top_srcdir)/lib/libalpm AM_CFLAGS = -pedantic -D_GNU_SOURCE diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 344f6a58..01c6b619 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -1,7 +1,7 @@ /* * callback.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,13 +18,12 @@ * 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 <sys/time.h> #include <sys/types.h> /* off_t */ +#include <time.h> #include <unistd.h> #include <wchar.h> #include <limits.h> /* UINT_MAX */ @@ -44,15 +43,19 @@ static off_t list_total = 0.0; static int on_progress = 0; static alpm_list_t *output = NULL; -/* Silly little helper function, determines if the caller needs a visual update +/* update speed for the fill_progress based functions */ +#define UPDATE_SPEED_MS 200 + +/** + * Silly little helper function, determines if the caller needs a visual update * since the last time this function was called. - * This is made for the two progress bar functions, to prevent flicker - * - * first_call indicates if this is the first time it is called, for - * initialization purposes */ -static double get_update_timediff(int first_call) + * This is made for the two progress bar functions, to prevent flicker. + * @param first_call 1 on first call for initialization purposes, 0 otherwise + * @return number of milliseconds since last call + */ +static long get_update_timediff(int first_call) { - double retval = 0.0; + long retval = 0; static struct timeval last_time = {0, 0}; /* on first call, simply set the last time and return */ @@ -60,18 +63,17 @@ static double get_update_timediff(int first_call) gettimeofday(&last_time, NULL); } else { struct timeval this_time; - double diff_sec, diff_usec; + time_t diff_sec; + suseconds_t diff_usec; gettimeofday(&this_time, NULL); diff_sec = this_time.tv_sec - last_time.tv_sec; diff_usec = this_time.tv_usec - last_time.tv_usec; - retval = diff_sec + (diff_usec / 1000000.0); + retval = (diff_sec * 1000) + (diff_usec / 1000); - /* return 0 and do not update last_time if interval was too short */ - if(retval < UPDATE_SPEED_SEC) { - retval = 0.0; - } else { + /* do not update last_time if interval was too short */ + if(retval >= UPDATE_SPEED_MS) { last_time = this_time; } } @@ -95,41 +97,41 @@ static void fill_progress(const int bar_percent, const int disp_percent, } if(hashlen > 0) { - printf(" ["); + fputs(" [", stdout); for(i = hashlen; i > 0; --i) { /* if special progress bar enabled */ if(config->chomp) { if(i > hashlen - hash) { - printf("-"); + putchar('-'); } else if(i == hashlen - hash) { if(lasthash == hash) { if(mouth) { - printf("\033[1;33mC\033[m"); + fputs("\033[1;33mC\033[m", stdout); } else { - printf("\033[1;33mc\033[m"); + fputs("\033[1;33mc\033[m", stdout); } } else { lasthash = hash; mouth = mouth == 1 ? 0 : 1; if(mouth) { - printf("\033[1;33mC\033[m"); + fputs("\033[1;33mC\033[m", stdout); } else { - printf("\033[1;33mc\033[m"); + fputs("\033[1;33mc\033[m", stdout); } } - } else if(i%3 == 0) { - printf("\033[0;37mo\033[m"); + } else if(i % 3 == 0) { + fputs("\033[0;37mo\033[m", stdout); } else { - printf("\033[0;37m \033[m"); + fputs("\033[0;37m \033[m", stdout); } } /* else regular progress bar */ else if(i > hashlen - hash) { - printf("#"); + putchar('#'); } else { - printf("-"); + putchar('-'); } } - printf("]"); + putchar(']'); } /* print display percent after progress bar */ /* 5 = 1 space + 3 digits + 1 % */ @@ -138,9 +140,9 @@ static void fill_progress(const int bar_percent, const int disp_percent, } if(bar_percent == 100) { - printf("\n"); + putchar('\n'); } else { - printf("\r"); + putchar('\r'); } fflush(stdout); } @@ -196,9 +198,9 @@ void cb_event(alpm_event_t event, void *data1, void *data2) break; case ALPM_EVENT_UPGRADE_DONE: alpm_logaction(config->handle, "upgraded %s (%s -> %s)\n", - (char *)alpm_pkg_get_name(data1), - (char *)alpm_pkg_get_version(data2), - (char *)alpm_pkg_get_version(data1)); + alpm_pkg_get_name(data1), + alpm_pkg_get_version(data2), + alpm_pkg_get_version(data1)); display_new_optdepends(data2,data1); break; case ALPM_EVENT_INTEGRITY_START: @@ -227,10 +229,10 @@ void cb_event(alpm_event_t event, void *data1, void *data2) printf(_("failed.\n")); break; case ALPM_EVENT_SCRIPTLET_INFO: - printf("%s", (char *)data1); + fputs((const char *)data1, stdout); break; case ALPM_EVENT_RETRIEVE_START: - printf(_(":: Retrieving packages from %s...\n"), (char *)data1); + printf(_(":: Retrieving packages ...\n")); break; case ALPM_EVENT_DISKSPACE_START: if(config->noprogressbar) { @@ -294,10 +296,10 @@ void cb_question(alpm_question_t event, void *data1, void *data2, break; case ALPM_QUESTION_REMOVE_PKGS: { - alpm_list_t *unresolved = (alpm_list_t *) data1; + alpm_list_t *unresolved = data1; alpm_list_t *namelist = NULL, *i; size_t count = 0; - for (i = unresolved; i; i = i->next) { + for(i = unresolved; i; i = i->next) { namelist = alpm_list_add(namelist, (char *)alpm_pkg_get_name(i->data)); count++; @@ -306,7 +308,7 @@ void cb_question(alpm_question_t event, void *data1, void *data2, ":: The following package cannot be upgraded due to unresolvable dependencies:\n", ":: The following packages cannot be upgraded due to unresolvable dependencies:\n", count)); - list_display(" ", namelist); + list_display(" ", namelist, getcols(fileno(stdout))); printf("\n"); *response = noyes(_n( "Do you want to skip the above package for this upgrade?", @@ -317,7 +319,7 @@ void cb_question(alpm_question_t event, void *data1, void *data2, break; case ALPM_QUESTION_SELECT_PROVIDER: { - alpm_list_t *providers = (alpm_list_t *)data1; + alpm_list_t *providers = data1; size_t count = alpm_list_count(providers); char *depstring = alpm_dep_compute_string((alpm_depend_t *)data2); printf(_(":: There are %zd providers available for %s:\n"), count, @@ -340,15 +342,22 @@ void cb_question(alpm_question_t event, void *data1, void *data2, *response = yesno(_(":: File %s is corrupted (%s).\n" "Do you want to delete it?"), (char *)data1, - alpm_strerror(*(enum _alpm_errno_t *)data2)); + alpm_strerror(*(alpm_errno_t *)data2)); break; case ALPM_QUESTION_IMPORT_KEY: { alpm_pgpkey_t *key = data1; char created[12]; - strftime(created, 12, "%Y-%m-%d", localtime(&(key->created))); - *response = yesno(_(":: Import PGP key %s, \"%s\", created %s?"), - key->fingerprint, key->uid, created); + const char *revoked = ""; + time_t time = (time_t)key->created; + strftime(created, 12, "%Y-%m-%d", localtime(&time)); + + if(key->revoked) { + revoked = " (revoked)"; + } + + *response = yesno(_(":: Import PGP key %d%c/%s, \"%s\", created: %s%s?"), + key->length, key->pubkey_algo, key->fingerprint, key->uid, created, revoked); } break; } @@ -375,7 +384,7 @@ void cb_progress(alpm_progress_t event, const char *pkgname, int percent, int len, wclen, wcwid, padwid; wchar_t *wcstr; - const unsigned short cols = getcols(); + const unsigned short cols = getcols(fileno(stdout)); if(config->noprogressbar || cols == 0) { return; @@ -393,7 +402,7 @@ void cb_progress(alpm_progress_t event, const char *pkgname, int percent, if(current != prevcurrent) { /* update always */ } else if(!pkgname || percent == prevpercent || - get_update_timediff(0) < UPDATE_SPEED_SEC) { + get_update_timediff(0) < UPDATE_SPEED_MS) { /* only update the progress bar when we have a package name, the * percentage has changed, and it has been long enough. */ return; @@ -493,7 +502,7 @@ void cb_progress(alpm_progress_t event, const char *pkgname, int percent, alpm_list_t *i = NULL; on_progress = 0; for(i = output; i; i = i->next) { - printf("%s", (char *)i->data); + fputs((const char *)i->data, stdout); } fflush(stdout); FREELIST(output); @@ -528,13 +537,14 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) int totaldownload = 0; off_t xfered, total; - double rate = 0.0, timediff = 0.0; + double rate = 0.0; + long timediff = 0; unsigned int eta_h = 0, eta_m = 0, eta_s = 0; double rate_human, xfered_human; const char *rate_label, *xfered_label; int file_percent = 0, total_percent = 0; - const unsigned short cols = getcols(); + const unsigned short cols = getcols(fileno(stdout)); if(config->noprogressbar || cols == 0 || file_total == -1) { if(file_xfered == 0) { @@ -587,16 +597,17 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) } else if(file_xfered == file_total) { /* compute final values */ struct timeval current_time; - double diff_sec, diff_usec; + time_t diff_sec; + suseconds_t diff_usec; gettimeofday(¤t_time, NULL); diff_sec = current_time.tv_sec - initial_time.tv_sec; diff_usec = current_time.tv_usec - initial_time.tv_usec; - timediff = diff_sec + (diff_usec / 1000000.0); - if(timediff > 0.0) { - rate = xfered / timediff; - /* round elapsed time to the nearest second */ - eta_s = (unsigned int)(timediff + 0.5); + timediff = (diff_sec * 1000) + (diff_usec / 1000); + if(timediff > 0) { + rate = (double)xfered / (timediff / 1000.0); + /* round elapsed time (in ms) to the nearest second */ + eta_s = (unsigned int)(timediff + 500) / 1000; } else { eta_s = 0; } @@ -604,11 +615,11 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) /* compute current average values */ timediff = get_update_timediff(0); - if(timediff < UPDATE_SPEED_SEC) { + if(timediff < UPDATE_SPEED_MS) { /* return if the calling interval was too short */ return; } - rate = (xfered - xfered_last) / timediff; + rate = (double)(xfered - xfered_last) / (timediff / 1000.0); /* average rate to reduce jumpiness */ rate = (rate + 2 * rate_last) / 3; if(rate > 0.0) { @@ -713,7 +724,7 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) } else if(eta_h < 100) { printf("%02u:%02u:%02u", eta_h, eta_m, eta_s); } else { - printf("--:--"); + fputs("--:--", stdout); } free(fname); diff --git a/src/pacman/callback.h b/src/pacman/callback.h index e328a22a..2215790a 100644 --- a/src/pacman/callback.h +++ b/src/pacman/callback.h @@ -1,7 +1,7 @@ /* * callback.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/src/pacman/conf.c b/src/pacman/conf.c index a9f0de91..4c3d063b 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -1,7 +1,7 @@ /* * conf.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <errno.h> #include <glob.h> #include <limits.h> @@ -54,6 +52,7 @@ config_t *config_new(void) newconfig->op = PM_OP_MAIN; newconfig->logmask = ALPM_LOG_ERROR | ALPM_LOG_WARNING; newconfig->configfile = strdup(CONFFILE); + newconfig->deltaratio = 0.0; if(alpm_capabilities() & ALPM_CAPABILITY_SIGNATURES) { newconfig->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL | ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; @@ -203,11 +202,14 @@ static int download_with_xfercommand(const char *url, const char *localpath, cleanup: /* restore the old cwd if we have it */ if(cwdfd >= 0) { + int ret; if(fchdir(cwdfd) != 0) { pm_printf(ALPM_LOG_ERROR, _("could not restore working directory (%s)\n"), strerror(errno)); } - close(cwdfd); + do { + ret = close(cwdfd); + } while(ret == -1 && errno == EINTR); } if(ret == -1) { @@ -256,11 +258,11 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage, const char *original = i->data, *value; int package = 0, database = 0; - if (strncmp(original, "Package", strlen("Package")) == 0) { + if(strncmp(original, "Package", strlen("Package")) == 0) { /* only packages are affected, don't flip flags for databases */ value = original + strlen("Package"); package = 1; - } else if (strncmp(original, "Database", strlen("Database")) == 0) { + } else if(strncmp(original, "Database", strlen("Database")) == 0) { /* only databases are affected, don't flip flags for packages */ value = original + strlen("Database"); database = 1; @@ -396,8 +398,8 @@ static int _parse_options(const char *key, char *value, config->verbosepkglists = 1; pm_printf(ALPM_LOG_DEBUG, "config: verbosepkglists\n"); } else if(strcmp(key, "UseDelta") == 0) { - config->usedelta = 1; - pm_printf(ALPM_LOG_DEBUG, "config: usedelta\n"); + config->deltaratio = 0.7; + pm_printf(ALPM_LOG_DEBUG, "config: usedelta (default 0.7)\n"); } else if(strcmp(key, "TotalDownload") == 0) { config->totaldownload = 1; pm_printf(ALPM_LOG_DEBUG, "config: totaldownload\n"); @@ -428,6 +430,18 @@ static int _parse_options(const char *key, char *value, if(!config->arch) { config_set_arch(value); } + } else if(strcmp(key, "UseDelta") == 0) { + double ratio; + char *endptr; + ratio = strtod(value, &endptr); + if(*endptr != '\0' || ratio < 0.0 || ratio > 2.0) { + pm_printf(ALPM_LOG_ERROR, + _("config file %s, line %d: invalid value for '%s' : '%s'\n"), + file, linenum, "UseDelta", value); + return 1; + } + config->deltaratio = ratio; + pm_printf(ALPM_LOG_DEBUG, "config: usedelta = %f\n", ratio); } else if(strcmp(key, "DBPath") == 0) { /* don't overwrite a path specified on the command line */ if(!config->dbpath) { @@ -522,7 +536,7 @@ static int _add_mirror(alpm_db_t *db, char *value) static int setup_libalpm(void) { int ret = 0; - enum _alpm_errno_t err; + alpm_errno_t err; alpm_handle_t *handle; pm_printf(ALPM_LOG_DEBUG, "setup_libalpm called\n"); @@ -604,7 +618,7 @@ static int setup_libalpm(void) alpm_option_set_arch(handle, config->arch); alpm_option_set_checkspace(handle, config->checkspace); alpm_option_set_usesyslog(handle, config->usesyslog); - alpm_option_set_usedelta(handle, config->usedelta); + alpm_option_set_deltaratio(handle, config->deltaratio); alpm_option_set_ignorepkgs(handle, config->ignorepkg); alpm_option_set_ignoregroups(handle, config->ignoregrp); @@ -650,7 +664,7 @@ static int finish_section(struct section_t *section, int parse_options) } /* if we are not looking at options sections only, register a db */ - db = alpm_db_register_sync(config->handle, section->name, section->siglevel); + db = alpm_register_syncdb(config->handle, section->name, section->siglevel); if(db == NULL) { pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)\n"), section->name, alpm_strerror(alpm_errno(config->handle))); @@ -659,7 +673,7 @@ static int finish_section(struct section_t *section, int parse_options) } for(i = section->servers; i; i = alpm_list_next(i)) { - char *value = alpm_list_getdata(i); + char *value = i->data; if(_add_mirror(db, value) != 0) { pm_printf(ALPM_LOG_ERROR, _("could not add mirror '%s' to database '%s' (%s)\n"), @@ -725,8 +739,7 @@ static int _parseconfig(const char *file, struct section_t *section, *ptr = '\0'; } - strtrim(line); - line_len = strlen(line); + line_len = strtrim(line); if(line_len == 0) { continue; @@ -822,7 +835,7 @@ static int _parseconfig(const char *file, struct section_t *section, if((ret = _parse_options(key, value, file, linenum)) != 0) { goto cleanup; } - } else if (!parse_options && !section->is_options) { + } else if(!parse_options && !section->is_options) { /* ... or in a repo section */ if(strcmp(key, "Server") == 0) { if(value == NULL) { @@ -859,7 +872,7 @@ static int _parseconfig(const char *file, struct section_t *section, } cleanup: - if (fp) { + if(fp) { fclose(fp); } pm_printf(ALPM_LOG_DEBUG, "config: finished parsing %s\n", file); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 42f25298..d3494c75 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -1,7 +1,7 @@ /* * conf.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -34,7 +34,7 @@ typedef struct __config_t { unsigned short print; unsigned short checkspace; unsigned short usesyslog; - unsigned short usedelta; + double deltaratio; char *arch; char *print_format; /* unfortunately, we have to keep track of paths both here and in the library @@ -127,7 +127,8 @@ enum { OP_ARCH, OP_PRINTFORMAT, OP_GPGDIR, - OP_DBONLY + OP_DBONLY, + OP_FORCE }; /* clean method */ diff --git a/src/pacman/database.c b/src/pacman/database.c index 3e4a672f..dd160135 100644 --- a/src/pacman/database.c +++ b/src/pacman/database.c @@ -1,7 +1,7 @@ /* * database.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdio.h> #include <alpm.h> @@ -63,11 +61,11 @@ int pacman_database(alpm_list_t *targets) return 1; } - db_local = alpm_option_get_localdb(config->handle); + db_local = alpm_get_localdb(config->handle); for(i = targets; i; i = alpm_list_next(i)) { char *pkgname = i->data; alpm_pkg_t *pkg = alpm_db_get_pkg(db_local, pkgname); - if(!pkg || alpm_db_set_pkgreason(config->handle, pkg, reason)) { + if(!pkg || alpm_pkg_set_reason(pkg, reason)) { pm_printf(ALPM_LOG_ERROR, _("could not set install reason for package %s (%s)\n"), pkgname, alpm_strerror(alpm_errno(config->handle))); retval = 1; diff --git a/src/pacman/deptest.c b/src/pacman/deptest.c index 0055c37e..a654c887 100644 --- a/src/pacman/deptest.c +++ b/src/pacman/deptest.c @@ -1,7 +1,7 @@ /* * deptest.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdio.h> #include <alpm.h> @@ -33,10 +31,10 @@ int pacman_deptest(alpm_list_t *targets) { alpm_list_t *i; alpm_list_t *deps = NULL; - alpm_db_t *localdb = alpm_option_get_localdb(config->handle); + alpm_db_t *localdb = alpm_get_localdb(config->handle); for(i = targets; i; i = alpm_list_next(i)) { - char *target = alpm_list_getdata(i); + char *target = i->data; if(!alpm_find_satisfier(alpm_db_get_pkgcache(localdb), target)) { deps = alpm_list_add(deps, target); @@ -48,7 +46,7 @@ int pacman_deptest(alpm_list_t *targets) } for(i = deps; i; i = alpm_list_next(i)) { - const char *dep = alpm_list_getdata(i); + const char *dep = i->data; printf("%s\n", dep); } diff --git a/src/pacman/package.c b/src/pacman/package.c index 97d89688..57bf6cef 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -1,7 +1,7 @@ /* * package.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,14 +18,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <limits.h> #include <errno.h> +#include <time.h> #include <alpm.h> #include <alpm_list.h> @@ -39,17 +38,31 @@ /** Turn a depends list into a text list. * @param deps a list with items of type alpm_depend_t - * @return a string list, must be freed */ static void deplist_display(const char *title, - alpm_list_t *deps) + alpm_list_t *deps, unsigned short cols) { alpm_list_t *i, *text = NULL; for(i = deps; i; i = alpm_list_next(i)) { - alpm_depend_t *dep = alpm_list_getdata(i); + alpm_depend_t *dep = i->data; text = alpm_list_add(text, alpm_dep_compute_string(dep)); } - list_display(title, text); + list_display(title, text, cols); + FREELIST(text); +} + +/** Turn a optdepends list into a text list. + * @param optdeps a list with items of type alpm_optdepend_t + */ +static void optdeplist_display(const char *title, + alpm_list_t *optdeps, unsigned short cols) +{ + alpm_list_t *i, *text = NULL; + for(i = optdeps; i; i = alpm_list_next(i)) { + alpm_depend_t *optdep = i->data; + text = alpm_list_add(text, alpm_dep_compute_string(optdep)); + } + list_display_linebreak(title, text, cols); FREELIST(text); } @@ -63,22 +76,22 @@ static void deplist_display(const char *title, */ void dump_pkg_full(alpm_pkg_t *pkg, int extra) { - const char *reason; + unsigned short cols; time_t bdate, idate; - char bdatestr[50] = "", idatestr[50] = ""; - const char *label; - double size; - alpm_list_t *requiredby = NULL; alpm_pkgfrom_t from; + double size; + char bdatestr[50] = "", idatestr[50] = ""; + const char *label, *reason; + alpm_list_t *validation = NULL, *requiredby = NULL; from = alpm_pkg_get_origin(pkg); /* set variables here, do all output below */ - bdate = alpm_pkg_get_builddate(pkg); + bdate = (time_t)alpm_pkg_get_builddate(pkg); if(bdate) { strftime(bdatestr, 50, "%c", localtime(&bdate)); } - idate = alpm_pkg_get_installdate(pkg); + idate = (time_t)alpm_pkg_get_installdate(pkg); if(idate) { strftime(idatestr, 50, "%c", localtime(&idate)); } @@ -95,75 +108,93 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) break; } - if(extra || from == PKG_FROM_LOCALDB) { + alpm_pkgvalidation_t v = alpm_pkg_get_validation(pkg); + if(v) { + if(v & ALPM_PKG_VALIDATION_NONE) { + validation = alpm_list_add(validation, _("None")); + } else { + if(v & ALPM_PKG_VALIDATION_MD5SUM) { + validation = alpm_list_add(validation, _("MD5 Sum")); + } + if(v & ALPM_PKG_VALIDATION_SHA256SUM) { + validation = alpm_list_add(validation, _("SHA256 Sum")); + } + if(v & ALPM_PKG_VALIDATION_SIGNATURE) { + validation = alpm_list_add(validation, _("Signature")); + } + } + } else { + validation = alpm_list_add(validation, _("Unknown")); + } + + if(extra || from == ALPM_PKG_FROM_LOCALDB) { /* compute this here so we don't get a pause in the middle of output */ requiredby = alpm_pkg_compute_requiredby(pkg); } + cols = getcols(fileno(stdout)); + /* actual output */ - if(from == PKG_FROM_SYNCDB) { + if(from == ALPM_PKG_FROM_SYNCDB) { string_display(_("Repository :"), - alpm_db_get_name(alpm_pkg_get_db(pkg))); + alpm_db_get_name(alpm_pkg_get_db(pkg)), cols); } - string_display(_("Name :"), alpm_pkg_get_name(pkg)); - string_display(_("Version :"), alpm_pkg_get_version(pkg)); - string_display(_("URL :"), alpm_pkg_get_url(pkg)); - list_display(_("Licenses :"), alpm_pkg_get_licenses(pkg)); - list_display(_("Groups :"), alpm_pkg_get_groups(pkg)); - deplist_display(_("Provides :"), alpm_pkg_get_provides(pkg)); - deplist_display(_("Depends On :"), alpm_pkg_get_depends(pkg)); - list_display_linebreak(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg)); - if(extra || from == PKG_FROM_LOCALDB) { - list_display(_("Required By :"), requiredby); + string_display(_("Name :"), alpm_pkg_get_name(pkg), cols); + string_display(_("Version :"), alpm_pkg_get_version(pkg), cols); + string_display(_("URL :"), alpm_pkg_get_url(pkg), cols); + list_display(_("Licenses :"), alpm_pkg_get_licenses(pkg), cols); + list_display(_("Groups :"), alpm_pkg_get_groups(pkg), cols); + deplist_display(_("Provides :"), alpm_pkg_get_provides(pkg), cols); + deplist_display(_("Depends On :"), alpm_pkg_get_depends(pkg), cols); + optdeplist_display(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg), cols); + if(extra || from == ALPM_PKG_FROM_LOCALDB) { + list_display(_("Required By :"), requiredby, cols); } - deplist_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg)); - deplist_display(_("Replaces :"), alpm_pkg_get_replaces(pkg)); + deplist_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg), cols); + deplist_display(_("Replaces :"), alpm_pkg_get_replaces(pkg), cols); size = humanize_size(alpm_pkg_get_size(pkg), 'K', 2, &label); - if(from == PKG_FROM_SYNCDB) { + if(from == ALPM_PKG_FROM_SYNCDB) { printf(_("Download Size : %6.2f %s\n"), size, label); - } else if(from == PKG_FROM_FILE) { + } else if(from == ALPM_PKG_FROM_FILE) { printf(_("Compressed Size: %6.2f %s\n"), size, label); } size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 2, &label); printf(_("Installed Size : %6.2f %s\n"), size, label); - string_display(_("Packager :"), alpm_pkg_get_packager(pkg)); - string_display(_("Architecture :"), alpm_pkg_get_arch(pkg)); - string_display(_("Build Date :"), bdatestr); - if(from == PKG_FROM_LOCALDB) { - string_display(_("Install Date :"), idatestr); - string_display(_("Install Reason :"), reason); + string_display(_("Packager :"), alpm_pkg_get_packager(pkg), cols); + string_display(_("Architecture :"), alpm_pkg_get_arch(pkg), cols); + string_display(_("Build Date :"), bdatestr, cols); + if(from == ALPM_PKG_FROM_LOCALDB) { + string_display(_("Install Date :"), idatestr, cols); + string_display(_("Install Reason :"), reason, cols); } - if(from == PKG_FROM_FILE || from == PKG_FROM_LOCALDB) { + if(from == ALPM_PKG_FROM_FILE || from == ALPM_PKG_FROM_LOCALDB) { string_display(_("Install Script :"), - alpm_pkg_has_scriptlet(pkg) ? _("Yes") : _("No")); + alpm_pkg_has_scriptlet(pkg) ? _("Yes") : _("No"), cols); } - if(from == PKG_FROM_SYNCDB) { - string_display(_("MD5 Sum :"), alpm_pkg_get_md5sum(pkg)); - string_display(_("SHA256 Sum :"), alpm_pkg_get_sha256sum(pkg)); - string_display(_("Signatures :"), - alpm_pkg_get_base64_sig(pkg) ? _("Yes") : _("None")); - } - if(from == PKG_FROM_FILE) { + list_display(_("Validated By :"), validation, cols); + + if(from == ALPM_PKG_FROM_FILE) { alpm_siglist_t siglist; int err = alpm_pkg_check_pgp_signature(pkg, &siglist); if(err && alpm_errno(config->handle) == ALPM_ERR_SIG_MISSING) { - string_display(_("Signatures :"), _("None")); + string_display(_("Signatures :"), _("None"), cols); } else if(err) { string_display(_("Signatures :"), - alpm_strerror(alpm_errno(config->handle))); + alpm_strerror(alpm_errno(config->handle)), cols); } else { - signature_display(_("Signatures :"), &siglist); + signature_display(_("Signatures :"), &siglist, cols); } alpm_siglist_cleanup(&siglist); } - string_display(_("Description :"), alpm_pkg_get_desc(pkg)); + + string_display(_("Description :"), alpm_pkg_get_desc(pkg), cols); /* Print additional package info if info flag passed more than once */ - if(from == PKG_FROM_LOCALDB && extra) { + if(from == ALPM_PKG_FROM_LOCALDB && extra) { dump_pkg_backups(pkg); } @@ -171,6 +202,7 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) printf("\n"); FREELIST(requiredby); + alpm_list_free(validation); } static const char *get_backup_file_status(const char *root, @@ -223,7 +255,7 @@ void dump_pkg_backups(alpm_pkg_t *pkg) if(alpm_pkg_get_backup(pkg)) { /* package has backup files, so print them */ for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) { - const alpm_backup_t *backup = alpm_list_getdata(i); + const alpm_backup_t *backup = i->data; const char *value; if(!backup->hash) { continue; @@ -251,11 +283,16 @@ void dump_pkg_files(alpm_pkg_t *pkg, int quiet) for(i = 0; i < pkgfiles->count; i++) { const alpm_file_t *file = pkgfiles->files + i; + /* Regular: '<pkgname> <root><filepath>\n' + * Quiet : '<root><filepath>\n' + */ if(!quiet) { - printf("%s %s%s\n", pkgname, root, file->name); - } else { - printf("%s%s\n", root, file->name); + fputs(pkgname, stdout); + putchar(' '); } + fputs(root, stdout); + fputs(file->name, stdout); + putchar('\n'); } fflush(stdout); @@ -280,10 +317,10 @@ void dump_pkg_changelog(alpm_pkg_t *pkg) /* if we hit the end of the file, we need to add a null terminator */ *(buf + ret) = '\0'; } - printf("%s", buf); + fputs(buf, stdout); } alpm_pkg_changelog_close(pkg, fp); - printf("\n"); + putchar('\n'); } } diff --git a/src/pacman/package.h b/src/pacman/package.h index 890b4fe1..1e021f4d 100644 --- a/src/pacman/package.h +++ b/src/pacman/package.h @@ -1,7 +1,7 @@ /* * package.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index c0c3bb8b..1e6797c9 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -1,7 +1,7 @@ /* * pacman.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - /* special handling of package version for GIT */ #if defined(GIT_VERSION) #undef PACKAGE_VERSION @@ -39,9 +37,6 @@ #include <sys/utsname.h> /* uname */ #include <locale.h> /* setlocale */ #include <errno.h> -#if defined(PACMAN_DEBUG) && defined(HAVE_MCHECK_H) -#include <mcheck.h> /* debug tracing (mtrace) */ -#endif /* alpm */ #include <alpm.h> @@ -178,7 +173,7 @@ static void usage(int op, const char * const myname) switch(op) { case PM_OP_SYNC: case PM_OP_UPGRADE: - addlist(_(" -f, --force force install, overwrite conflicting files\n")); + addlist(_(" --force force install, overwrite conflicting files\n")); addlist(_(" --asdeps install packages as non-explicitly installed\n")); addlist(_(" --asexplicit install packages as explicitly installed\n")); addlist(_(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n")); @@ -208,8 +203,8 @@ static void usage(int op, const char * const myname) addlist(_(" --noconfirm do not ask for any confirmation\n")); } list = alpm_list_msort(list, alpm_list_count(list), options_cmp); - for (i = list; i; i = alpm_list_next(i)) { - printf("%s", (char *)alpm_list_getdata(i)); + for(i = list; i; i = alpm_list_next(i)) { + fputs((const char *)i->data, stdout); } alpm_list_free(list); #undef addlist @@ -528,7 +523,7 @@ static int parsearg_upgrade(int opt) if(parsearg_trans(opt) == 0) return 0; switch(opt) { - case 'f': config->flags |= ALPM_TRANS_FLAG_FORCE; break; + case OP_FORCE: config->flags |= ALPM_TRANS_FLAG_FORCE; break; case OP_ASDEPS: config->flags |= ALPM_TRANS_FLAG_ALLDEPS; break; case OP_ASEXPLICIT: config->flags |= ALPM_TRANS_FLAG_ALLEXPLICIT; break; case OP_NEEDED: config->flags |= ALPM_TRANS_FLAG_NEEDED; break; @@ -593,7 +588,6 @@ static int parseargs(int argc, char *argv[]) {"nodeps", no_argument, 0, 'd'}, {"deps", no_argument, 0, 'd'}, {"explicit", no_argument, 0, 'e'}, - {"force", no_argument, 0, 'f'}, {"groups", no_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, {"info", no_argument, 0, 'i'}, @@ -620,6 +614,7 @@ static int parseargs(int argc, char *argv[]) {"config", required_argument, 0, OP_CONFIG}, {"ignore", required_argument, 0, OP_IGNORE}, {"debug", optional_argument, 0, OP_DEBUG}, + {"force", no_argument, 0, OP_FORCE}, {"noprogressbar", no_argument, 0, OP_NOPROGRESSBAR}, {"noscriptlet", no_argument, 0, OP_NOSCRIPTLET}, {"ask", required_argument, 0, OP_ASK}, @@ -765,11 +760,6 @@ int main(int argc, char *argv[]) uid_t myuid = geteuid(); #endif -#if defined(PACMAN_DEBUG) && defined(HAVE_MCHECK_H) - /*setenv("MALLOC_TRACE","pacman.mtrace", 0);*/ - mtrace(); -#endif - /* Set signal handlers */ /* Set up the structure to specify the new action. */ new_action.sa_handler = handler; @@ -901,13 +891,13 @@ int main(int argc, char *argv[]) printf("DB Path : %s\n", alpm_option_get_dbpath(config->handle)); printf("Cache Dirs: "); for(i = alpm_option_get_cachedirs(config->handle); i; i = alpm_list_next(i)) { - printf("%s ", (char *)alpm_list_getdata(i)); + printf("%s ", (const char *)i->data); } printf("\n"); printf("Lock File : %s\n", alpm_option_get_lockfile(config->handle)); printf("Log File : %s\n", alpm_option_get_logfile(config->handle)); printf("GPG Dir : %s\n", alpm_option_get_gpgdir(config->handle)); - list_display("Targets :", pm_targets); + list_display("Targets :", pm_targets, 0); } /* Log command line */ diff --git a/src/pacman/pacman.h b/src/pacman/pacman.h index 8bb9cb27..710e8fdc 100644 --- a/src/pacman/pacman.h +++ b/src/pacman/pacman.h @@ -1,7 +1,7 @@ /* * pacman.h * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify diff --git a/src/pacman/query.c b/src/pacman/query.c index ab19bab2..a1cc1cf9 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -1,7 +1,7 @@ /* * query.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <stdint.h> @@ -134,7 +132,7 @@ static int query_fileowner(alpm_list_t *targets) } strcpy(path, root); - db_local = alpm_option_get_localdb(config->handle); + db_local = alpm_get_localdb(config->handle); for(t = targets; t; t = alpm_list_next(t)) { char *filename, *dname, *rpath; @@ -143,7 +141,7 @@ static int query_fileowner(alpm_list_t *targets) alpm_list_t *i; int found = 0; - filename = strdup(alpm_list_getdata(t)); + filename = strdup(t->data); if(lstat(filename, &buf) == -1) { /* if it is not a path but a program name, then check in PATH */ @@ -193,7 +191,7 @@ static int query_fileowner(alpm_list_t *targets) free(dname); for(i = alpm_db_get_pkgcache(db_local); i && !found; i = alpm_list_next(i)) { - alpm_pkg_t *info = alpm_list_getdata(i); + alpm_pkg_t *info = i->data; alpm_filelist_t *filelist = alpm_pkg_get_files(info); size_t j; @@ -247,7 +245,8 @@ static int query_search(alpm_list_t *targets) { alpm_list_t *i, *searchlist; int freelist; - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); + unsigned short cols; /* if we have a targets list, search for packages matching it */ if(targets) { @@ -261,37 +260,38 @@ static int query_search(alpm_list_t *targets) return 1; } + cols = getcols(fileno(stdout)); for(i = searchlist; i; i = alpm_list_next(i)) { alpm_list_t *grp; - alpm_pkg_t *pkg = alpm_list_getdata(i); + alpm_pkg_t *pkg = i->data; if(!config->quiet) { printf("local/%s %s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); } else { - printf("%s", alpm_pkg_get_name(pkg)); + fputs(alpm_pkg_get_name(pkg), stdout); } if(!config->quiet) { if((grp = alpm_pkg_get_groups(pkg)) != NULL) { alpm_list_t *k; - printf(" ("); + fputs(" (", stdout); for(k = grp; k; k = alpm_list_next(k)) { - const char *group = alpm_list_getdata(k); - printf("%s", group); + const char *group = k->data; + fputs(group, stdout); if(alpm_list_next(k)) { /* only print a spacer if there are more groups */ - printf(" "); + putchar(' '); } } - printf(")"); + putchar(')'); } /* we need a newline and initial indent first */ - printf("\n "); - indentprint(alpm_pkg_get_desc(pkg), 4); + fputs("\n ", stdout); + indentprint(alpm_pkg_get_desc(pkg), 4, cols); } - printf("\n"); + fputc('\n', stdout); } /* we only want to free if the list was a search list */ @@ -304,33 +304,33 @@ static int query_search(alpm_list_t *targets) static int query_group(alpm_list_t *targets) { alpm_list_t *i, *j; - char *grpname = NULL; + const char *grpname = NULL; int ret = 0; - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); if(targets == NULL) { for(j = alpm_db_get_groupcache(db_local); j; j = alpm_list_next(j)) { - alpm_group_t *grp = alpm_list_getdata(j); + alpm_group_t *grp = j->data; const alpm_list_t *p; for(p = grp->packages; p; p = alpm_list_next(p)) { - alpm_pkg_t *pkg = alpm_list_getdata(p); + alpm_pkg_t *pkg = p->data; printf("%s %s\n", grp->name, alpm_pkg_get_name(pkg)); } } } else { for(i = targets; i; i = alpm_list_next(i)) { alpm_group_t *grp; - grpname = alpm_list_getdata(i); - grp = alpm_db_readgroup(db_local, grpname); + grpname = i->data; + grp = alpm_db_get_group(db_local, grpname); if(grp) { const alpm_list_t *p; for(p = grp->packages; p; p = alpm_list_next(p)) { if(!config->quiet) { printf("%s %s\n", grpname, - alpm_pkg_get_name(alpm_list_getdata(p))); + alpm_pkg_get_name(p->data)); } else { - printf("%s\n", alpm_pkg_get_name(alpm_list_getdata(p))); + printf("%s\n", alpm_pkg_get_name(p->data)); } } } else { @@ -346,11 +346,11 @@ static int is_foreign(alpm_pkg_t *pkg) { const char *pkgname = alpm_pkg_get_name(pkg); alpm_list_t *j; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle); + alpm_list_t *sync_dbs = alpm_get_syncdbs(config->handle); int match = 0; for(j = sync_dbs; j; j = alpm_list_next(j)) { - alpm_db_t *db = alpm_list_getdata(j); + alpm_db_t *db = j->data; alpm_pkg_t *findpkg = alpm_db_get_pkg(db, pkgname); if(findpkg) { match = 1; @@ -395,7 +395,7 @@ static int filter(alpm_pkg_t *pkg) } /* check if this pkg is outdated */ if(config->op_q_upgrade && (alpm_sync_newversion(pkg, - alpm_option_get_syncdbs(config->handle)) == NULL)) { + alpm_get_syncdbs(config->handle)) == NULL)) { return 0; } return 1; @@ -514,7 +514,7 @@ int pacman_query(alpm_list_t *targets) } } - db_local = alpm_option_get_localdb(config->handle); + db_local = alpm_get_localdb(config->handle); /* operations on all packages in the local DB * valid: no-op (plain -Q), list, info, check @@ -526,7 +526,7 @@ int pacman_query(alpm_list_t *targets) } for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) { - pkg = alpm_list_getdata(i); + pkg = i->data; if(filter(pkg)) { int value = display(pkg); if(value != 0) { @@ -552,7 +552,7 @@ int pacman_query(alpm_list_t *targets) /* operations on named packages in the local DB * valid: no-op (plain -Q), list, info, check */ for(i = targets; i; i = alpm_list_next(i)) { - char *strname = alpm_list_getdata(i); + const char *strname = i->data; if(config->op_q_isfile) { alpm_pkg_load(config->handle, strname, 1, 0, &pkg); diff --git a/src/pacman/remove.c b/src/pacman/remove.c index e7453c8d..472adb52 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -1,7 +1,7 @@ /* * remove.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - +#include <fnmatch.h> #include <stdlib.h> #include <stdio.h> @@ -31,10 +30,15 @@ #include "util.h" #include "conf.h" +static int fnmatch_cmp(const void *pattern, const void *string) +{ + return fnmatch(pattern, string, 0); +} + static int remove_target(const char *target) { alpm_pkg_t *pkg; - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); alpm_list_t *p; if((pkg = alpm_db_get_pkg(db_local, target)) != NULL) { @@ -48,13 +52,13 @@ static int remove_target(const char *target) } /* fallback to group */ - alpm_group_t *grp = alpm_db_readgroup(db_local, target); + alpm_group_t *grp = alpm_db_get_group(db_local, target); if(grp == NULL) { pm_printf(ALPM_LOG_ERROR, _("target not found: %s\n"), target); return -1; } for(p = grp->packages; p; p = alpm_list_next(p)) { - pkg = alpm_list_getdata(p); + pkg = p->data; if(alpm_remove_pkg(config->handle, pkg) == -1) { pm_printf(ALPM_LOG_ERROR, "'%s': %s\n", target, alpm_strerror(alpm_errno(config->handle))); @@ -89,7 +93,7 @@ int pacman_remove(alpm_list_t *targets) /* Step 1: add targets to the created transaction */ for(i = targets; i; i = alpm_list_next(i)) { - char *target = alpm_list_getdata(i); + char *target = i->data; char *targ = strchr(target, '/'); if(targ && strncmp(target, "local", 5) == 0) { targ++; @@ -98,25 +102,22 @@ int pacman_remove(alpm_list_t *targets) } if(remove_target(targ) == -1) { retval = 1; - goto cleanup; } } + if(retval == 1) { + goto cleanup; + } + /* Step 2: prepare the transaction based on its type, targets and flags */ if(alpm_trans_prepare(config->handle, &data) == -1) { - enum _alpm_errno_t err = alpm_errno(config->handle); + alpm_errno_t err = alpm_errno(config->handle); pm_printf(ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerror(err)); switch(err) { - case ALPM_ERR_PKG_INVALID_ARCH: - for(i = data; i; i = alpm_list_next(i)) { - char *pkg = alpm_list_getdata(i); - printf(_(":: package %s does not have a valid architecture\n"), pkg); - } - break; case ALPM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { - alpm_depmissing_t *miss = alpm_list_getdata(i); + alpm_depmissing_t *miss = i->data; char *depstring = alpm_dep_compute_string(miss->depend); printf(_(":: %s: requires %s\n"), miss->target, depstring); free(depstring); @@ -133,8 +134,8 @@ int pacman_remove(alpm_list_t *targets) /* Search for holdpkg in target list */ int holdpkg = 0; for(i = alpm_trans_get_remove(config->handle); i; i = alpm_list_next(i)) { - alpm_pkg_t *pkg = alpm_list_getdata(i); - if(alpm_list_find_str(config->holdpkg, alpm_pkg_get_name(pkg))) { + alpm_pkg_t *pkg = i->data; + if(alpm_list_find(config->holdpkg, alpm_pkg_get_name(pkg), fnmatch_cmp)) { pm_printf(ALPM_LOG_WARNING, _("%s is designated as a HoldPkg.\n"), alpm_pkg_get_name(pkg)); holdpkg = 1; diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 951ee94c..5165dca1 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -68,7 +66,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) return 1; } - syncdbs = alpm_option_get_syncdbs(config->handle); + syncdbs = alpm_get_syncdbs(config->handle); rewinddir(dir); /* step through the directory one file at a time */ @@ -118,7 +116,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) if(keep_used) { alpm_list_t *i; for(i = syncdbs; i && !found; i = alpm_list_next(i)) { - alpm_db_t *db = alpm_list_getdata(i); + alpm_db_t *db = i->data; found = !strcmp(dbname, alpm_db_get_name(db)); } } @@ -169,13 +167,13 @@ static int sync_cleandb_all(void) static int sync_cleancache(int level) { alpm_list_t *i; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle); - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + alpm_list_t *sync_dbs = alpm_get_syncdbs(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); alpm_list_t *cachedirs = alpm_option_get_cachedirs(config->handle); int ret = 0; for(i = cachedirs; i; i = alpm_list_next(i)) { - printf(_("Cache directory: %s\n"), (char *)alpm_list_getdata(i)); + printf(_("Cache directory: %s\n"), (const char *)i->data); } if(!config->cleanmethod) { @@ -203,7 +201,7 @@ static int sync_cleancache(int level) } for(i = cachedirs; i; i = alpm_list_next(i)) { - const char *cachedir = alpm_list_getdata(i); + const char *cachedir = i->data; DIR *dir = opendir(cachedir); struct dirent *ent; @@ -276,7 +274,7 @@ static int sync_cleancache(int level) alpm_list_t *j; /* check if this package is in a sync DB */ for(j = sync_dbs; j && delete; j = alpm_list_next(j)) { - alpm_db_t *db = alpm_list_getdata(j); + alpm_db_t *db = j->data; pkg = alpm_db_get_pkg(db, local_name); if(pkg != NULL && alpm_pkg_vercmp(local_version, alpm_pkg_get_version(pkg)) == 0) { @@ -312,7 +310,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) int success = 0, ret; for(i = syncs; i; i = alpm_list_next(i)) { - alpm_db_t *db = alpm_list_getdata(i); + alpm_db_t *db = i->data; ret = alpm_db_update((level < 2 ? 0 : 1), db); if(ret < 0) { @@ -358,10 +356,11 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) alpm_list_t *i, *j, *ret; int freelist; int found = 0; - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); for(i = syncs; i; i = alpm_list_next(i)) { - alpm_db_t *db = alpm_list_getdata(i); + alpm_db_t *db = i->data; + unsigned short cols; /* if we have a targets list, search for packages matching it */ if(targets) { ret = alpm_db_search(db, targets); @@ -375,39 +374,40 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) } else { found = 1; } + cols = getcols(fileno(stdout)); for(j = ret; j; j = alpm_list_next(j)) { alpm_list_t *grp; - alpm_pkg_t *pkg = alpm_list_getdata(j); + alpm_pkg_t *pkg = j->data; if(!config->quiet) { printf("%s/%s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); } else { - printf("%s", alpm_pkg_get_name(pkg)); + fputs(alpm_pkg_get_name(pkg), stdout); } if(!config->quiet) { if((grp = alpm_pkg_get_groups(pkg)) != NULL) { alpm_list_t *k; - printf(" ("); + fputs(" (", stdout); for(k = grp; k; k = alpm_list_next(k)) { - const char *group = alpm_list_getdata(k); - printf("%s", group); + const char *group = k->data; + fputs(group, stdout); if(alpm_list_next(k)) { /* only print a spacer if there are more groups */ - printf(" "); + putchar(' '); } } - printf(")"); + putchar(')'); } print_installed(db_local, pkg); /* we need a newline and initial indent first */ - printf("\n "); - indentprint(alpm_pkg_get_desc(pkg), 4); + fputs("\n ", stdout); + indentprint(alpm_pkg_get_desc(pkg), 4, cols); } - printf("\n"); + fputc('\n', stdout); } /* we only want to free if the list was a search list */ if(freelist) { @@ -420,23 +420,23 @@ 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, *k; + alpm_list_t *i, *j, *k, *s = NULL; if(targets) { for(i = targets; i; i = alpm_list_next(i)) { - const char *grpname = alpm_list_getdata(i); + const char *grpname = i->data; for(j = syncs; j; j = alpm_list_next(j)) { - alpm_db_t *db = alpm_list_getdata(j); - alpm_group_t *grp = alpm_db_readgroup(db, grpname); + alpm_db_t *db = j->data; + alpm_group_t *grp = alpm_db_get_group(db, grpname); if(grp) { /* get names of packages in group */ for(k = grp->packages; k; k = alpm_list_next(k)) { if(!config->quiet) { printf("%s %s\n", grpname, - alpm_pkg_get_name(alpm_list_getdata(k))); + alpm_pkg_get_name(k->data)); } else { - printf("%s\n", alpm_pkg_get_name(alpm_list_getdata(k))); + printf("%s\n", alpm_pkg_get_name(k->data)); } } } @@ -444,22 +444,26 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) } } else { for(i = syncs; i; i = alpm_list_next(i)) { - alpm_db_t *db = alpm_list_getdata(i); + alpm_db_t *db = i->data; for(j = alpm_db_get_groupcache(db); j; j = alpm_list_next(j)) { - alpm_group_t *grp = alpm_list_getdata(j); + alpm_group_t *grp = j->data; if(level > 1) { for(k = grp->packages; k; k = alpm_list_next(k)) { printf("%s %s\n", grp->name, - alpm_pkg_get_name(alpm_list_getdata(k))); + alpm_pkg_get_name(k->data)); } } else { /* print grp names only, no package names */ - printf("%s\n", grp->name); + if(!alpm_list_find_str (s, grp->name)) { + s = alpm_list_add (s, grp->name); + printf("%s\n", grp->name); + } } } } + alpm_list_free(s); } return 0; @@ -472,7 +476,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) if(targets) { for(i = targets; i; i = alpm_list_next(i)) { - const char *target = alpm_list_getdata(i); + const char *target = i->data; char *name = strdup(target); char *repo, *pkgstr; int foundpkg = 0, founddb = 0; @@ -488,14 +492,14 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } for(j = syncs; j; j = alpm_list_next(j)) { - alpm_db_t *db = alpm_list_getdata(j); + alpm_db_t *db = j->data; if(repo && strcmp(repo, alpm_db_get_name(db)) != 0) { continue; } founddb = 1; for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) { - alpm_pkg_t *pkg = alpm_list_getdata(k); + alpm_pkg_t *pkg = k->data; if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { dump_pkg_full(pkg, config->op_s_info > 1); @@ -519,10 +523,10 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) } } else { for(i = syncs; i; i = alpm_list_next(i)) { - alpm_db_t *db = alpm_list_getdata(i); + alpm_db_t *db = i->data; for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { - alpm_pkg_t *pkg = alpm_list_getdata(j); + alpm_pkg_t *pkg = j->data; dump_pkg_full(pkg, config->op_s_info > 1); } } @@ -534,15 +538,15 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) { alpm_list_t *i, *j, *ls = NULL; - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); if(targets) { for(i = targets; i; i = alpm_list_next(i)) { - const char *repo = alpm_list_getdata(i); + const char *repo = i->data; alpm_db_t *db = NULL; for(j = syncs; j; j = alpm_list_next(j)) { - alpm_db_t *d = alpm_list_getdata(j); + alpm_db_t *d = j->data; if(strcmp(repo, alpm_db_get_name(d)) == 0) { db = d; @@ -564,10 +568,10 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) } for(i = ls; i; i = alpm_list_next(i)) { - alpm_db_t *db = alpm_list_getdata(i); + alpm_db_t *db = i->data; for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { - alpm_pkg_t *pkg = alpm_list_getdata(j); + alpm_pkg_t *pkg = j->data; if(!config->quiet) { printf("%s %s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg), @@ -589,11 +593,11 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) static alpm_list_t *syncfirst(void) { alpm_list_t *i, *res = NULL; - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); - alpm_list_t *syncdbs = alpm_option_get_syncdbs(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); + alpm_list_t *syncdbs = alpm_get_syncdbs(config->handle); for(i = config->syncfirst; i; i = alpm_list_next(i)) { - char *pkgname = alpm_list_getdata(i); + const char *pkgname = i->data; alpm_pkg_t *pkg = alpm_db_get_pkg(db_local, pkgname); if(pkg == NULL) { continue; @@ -610,7 +614,7 @@ static alpm_list_t *syncfirst(void) { static alpm_db_t *get_db(const char *dbname) { alpm_list_t *i; - for(i = alpm_option_get_syncdbs(config->handle); i; i = i->next) { + for(i = alpm_get_syncdbs(config->handle); i; i = i->next) { alpm_db_t *db = i->data; if(strcmp(alpm_db_get_name(db), dbname) == 0) { return db; @@ -624,7 +628,7 @@ static int process_pkg(alpm_pkg_t *pkg) int ret = alpm_add_pkg(config->handle, pkg); if(ret == -1) { - enum _alpm_errno_t err = alpm_errno(config->handle); + alpm_errno_t err = alpm_errno(config->handle); if(err == ALPM_ERR_TRANS_DUP_TARGET || err == ALPM_ERR_PKG_IGNORED) { /* just skip duplicate or ignored targets */ @@ -640,7 +644,7 @@ static int process_pkg(alpm_pkg_t *pkg) return 0; } -static int process_group(alpm_list_t *dbs, const char *group) +static int process_group(alpm_list_t *dbs, const char *group, int error) { int ret = 0; alpm_list_t *i; @@ -652,6 +656,12 @@ static int process_group(alpm_list_t *dbs, const char *group) return 1; } + if(error) { + /* we already know another target errored. there is no reason to prompt the + * user here; we already validated the group name so just move on since we + * won't actually be installing anything anyway. */ + goto cleanup; + } if(config->print == 0) { printf(_(":: There are %d members in group %s:\n"), count, @@ -671,7 +681,7 @@ static int process_group(alpm_list_t *dbs, const char *group) for(i = pkgs; i; i = alpm_list_next(i)) { if(array[n++] == 0) continue; - alpm_pkg_t *pkg = alpm_list_getdata(i); + alpm_pkg_t *pkg = i->data; if(process_pkg(pkg) == 1) { ret = 1; @@ -682,7 +692,7 @@ static int process_group(alpm_list_t *dbs, const char *group) free(array); } else { for(i = pkgs; i; i = alpm_list_next(i)) { - alpm_pkg_t *pkg = alpm_list_getdata(i); + alpm_pkg_t *pkg = i->data; if(process_pkg(pkg) == 1) { ret = 1; @@ -690,12 +700,14 @@ static int process_group(alpm_list_t *dbs, const char *group) } } } + cleanup: alpm_list_free(pkgs); return ret; } -static int process_targname(alpm_list_t *dblist, const char *targname) +static int process_targname(alpm_list_t *dblist, const char *targname, + int error) { alpm_pkg_t *pkg = alpm_find_dbs_satisfier(config->handle, dblist, targname); @@ -709,20 +721,20 @@ static int process_targname(alpm_list_t *dblist, const char *targname) return process_pkg(pkg); } /* fallback on group */ - return process_group(dblist, targname); + return process_group(dblist, targname, error); } -static int process_target(const char *target) +static int process_target(const char *target, int error) { /* process targets */ char *targstring = strdup(target); char *targname = strchr(targstring, '/'); - char *dbname = NULL; int ret = 0; - alpm_list_t *dblist = NULL; + alpm_list_t *dblist; if(targname && targname != targstring) { - alpm_db_t *db = NULL; + alpm_db_t *db; + const char *dbname; *targname = '\0'; targname++; @@ -734,14 +746,15 @@ static int process_target(const char *target) ret = 1; goto cleanup; } - dblist = alpm_list_add(dblist, db); - ret = process_targname(dblist, targname); + dblist = alpm_list_add(NULL, db); + ret = process_targname(dblist, targname, error); alpm_list_free(dblist); } else { targname = targstring; - dblist = alpm_option_get_syncdbs(config->handle); - ret = process_targname(dblist, targname); + dblist = alpm_get_syncdbs(config->handle); + ret = process_targname(dblist, targname, error); } + cleanup: free(targstring); if(ret && access(target, R_OK) == 0) { @@ -754,6 +767,7 @@ cleanup: static int sync_trans(alpm_list_t *targets) { + int retval = 0; alpm_list_t *i; /* Step 1: create a new transaction... */ @@ -763,13 +777,17 @@ static int sync_trans(alpm_list_t *targets) /* process targets */ for(i = targets; i; i = alpm_list_next(i)) { - char *targ = alpm_list_getdata(i); - if(process_target(targ) == 1) { - trans_release(); - return 1; + const char *targ = i->data; + if(process_target(targ, retval) == 1) { + retval = 1; } } + if(retval) { + trans_release(); + return retval; + } + if(config->op_s_upgrade) { printf(_(":: Starting full system upgrade...\n")); alpm_logaction(config->handle, "starting full system upgrade\n"); @@ -790,19 +808,19 @@ int sync_prepare_execute(void) /* Step 2: "compute" the transaction based on targets and flags */ if(alpm_trans_prepare(config->handle, &data) == -1) { - enum _alpm_errno_t err = alpm_errno(config->handle); + alpm_errno_t err = alpm_errno(config->handle); pm_printf(ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerror(err)); switch(err) { case ALPM_ERR_PKG_INVALID_ARCH: for(i = data; i; i = alpm_list_next(i)) { - char *pkg = alpm_list_getdata(i); + const char *pkg = i->data; printf(_(":: package %s does not have a valid architecture\n"), pkg); } break; case ALPM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { - alpm_depmissing_t *miss = alpm_list_getdata(i); + alpm_depmissing_t *miss = i->data; char *depstring = alpm_dep_compute_string(miss->depend); printf(_(":: %s: requires %s\n"), miss->target, depstring); free(depstring); @@ -810,7 +828,7 @@ int sync_prepare_execute(void) break; case ALPM_ERR_CONFLICTING_DEPS: for(i = data; i; i = alpm_list_next(i)) { - alpm_conflict_t *conflict = alpm_list_getdata(i); + alpm_conflict_t *conflict = i->data; /* only print reason if it contains new information */ if(conflict->reason->mod == ALPM_DEP_MOD_ANY) { printf(_(":: %s and %s are in conflict\n"), @@ -859,13 +877,13 @@ int sync_prepare_execute(void) } if(alpm_trans_commit(config->handle, &data) == -1) { - enum _alpm_errno_t err = alpm_errno(config->handle); + alpm_errno_t err = alpm_errno(config->handle); pm_printf(ALPM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerror(err)); switch(err) { case ALPM_ERR_FILE_CONFLICTS: for(i = data; i; i = alpm_list_next(i)) { - alpm_fileconflict_t *conflict = alpm_list_getdata(i); + alpm_fileconflict_t *conflict = i->data; switch(conflict->type) { case ALPM_FILECONFLICT_TARGET: printf(_("%s exists in both '%s' and '%s'\n"), @@ -883,7 +901,7 @@ int sync_prepare_execute(void) case ALPM_ERR_PKG_INVALID_SIG: case ALPM_ERR_DLT_INVALID: for(i = data; i; i = alpm_list_next(i)) { - const char *filename = alpm_list_getdata(i); + const char *filename = i->data; printf(_("%s is invalid or corrupted\n"), filename); } break; @@ -935,7 +953,7 @@ int pacman_sync(alpm_list_t *targets) return 1; } - sync_dbs = alpm_option_get_syncdbs(config->handle); + sync_dbs = alpm_get_syncdbs(config->handle); if(config->op_s_sync) { /* grab a fresh package list */ @@ -993,7 +1011,7 @@ int pacman_sync(alpm_list_t *targets) if(config->op_s_upgrade || (tmp = alpm_list_diff(targets, packages, (alpm_list_fn_cmp)strcmp))) { alpm_list_free(tmp); printf(_(":: The following packages should be upgraded first :\n")); - list_display(" ", packages); + list_display(" ", packages, getcols(fileno(stdout))); if(yesno(_(":: Do you want to cancel the current operation\n" ":: and upgrade these packages now?"))) { FREELIST(targs); diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c index 880aa4c6..eaa36402 100644 --- a/src/pacman/upgrade.c +++ b/src/pacman/upgrade.c @@ -1,7 +1,7 @@ /* * upgrade.c * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -41,6 +39,7 @@ */ int pacman_upgrade(alpm_list_t *targets) { + int retval = 0; alpm_list_t *i; alpm_siglevel_t level = alpm_option_get_default_siglevel(config->handle); @@ -57,7 +56,7 @@ int pacman_upgrade(alpm_list_t *targets) if(str == NULL) { pm_printf(ALPM_LOG_ERROR, "'%s': %s\n", (char *)i->data, alpm_strerror(alpm_errno(config->handle))); - return 1; + retval = 1; } else { free(i->data); i->data = str; @@ -65,6 +64,10 @@ int pacman_upgrade(alpm_list_t *targets) } } + if(retval) { + return retval; + } + /* Step 1: create a new transaction */ if(trans_init(config->flags, 1) == -1) { return 1; @@ -73,25 +76,30 @@ int pacman_upgrade(alpm_list_t *targets) printf(_("loading packages...\n")); /* add targets to the created transaction */ for(i = targets; i; i = alpm_list_next(i)) { - char *targ = alpm_list_getdata(i); + const char *targ = i->data; alpm_pkg_t *pkg; if(alpm_pkg_load(config->handle, targ, 1, level, &pkg) != 0) { pm_printf(ALPM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerror(alpm_errno(config->handle))); - trans_release(); - return 1; + retval = 1; + continue; } if(alpm_add_pkg(config->handle, pkg) == -1) { pm_printf(ALPM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerror(alpm_errno(config->handle))); alpm_pkg_free(pkg); - trans_release(); - return 1; + retval = 1; + continue; } config->explicit_adds = alpm_list_add(config->explicit_adds, pkg); } + if(retval) { + trans_release(); + return retval; + } + /* now that targets are resolved, we can hand it all off to the sync code */ return sync_prepare_execute(); } diff --git a/src/pacman/util.c b/src/pacman/util.c index f7f8ecf5..f2ab163b 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -18,12 +18,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <sys/types.h> #include <sys/ioctl.h> #include <sys/stat.h> -#include <sys/time.h> +#include <time.h> #include <stdio.h> #include <stdlib.h> @@ -65,7 +63,7 @@ int trans_init(alpm_transflag_t flags, int check_valid) void trans_init_error(void) { - enum _alpm_errno_t err = alpm_errno(config->handle); + alpm_errno_t err = alpm_errno(config->handle); pm_printf(ALPM_LOG_ERROR, _("failed to init transaction (%s)\n"), alpm_strerror(err)); if(err == ALPM_ERR_HANDLE_LOCK) { @@ -110,7 +108,7 @@ int check_syncdbs(size_t need_repos, int check_valid) { int ret = 0; alpm_list_t *i; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle); + alpm_list_t *sync_dbs = alpm_get_syncdbs(config->handle); if(need_repos && sync_dbs == NULL) { pm_printf(ALPM_LOG_ERROR, _("no usable package repositories configured.\n")); @@ -132,10 +130,10 @@ int check_syncdbs(size_t need_repos, int check_valid) } /* discard unhandled input on the terminal's input buffer */ -static int flush_term_input(void) { +static int flush_term_input(int fd) { #ifdef HAVE_TCFLUSH - if(isatty(fileno(stdin))) { - return tcflush(fileno(stdin), TCIFLUSH); + if(isatty(fd)) { + return tcflush(fd, TCIFLUSH); } #endif @@ -144,24 +142,24 @@ static int flush_term_input(void) { } /* gets the current screen column width */ -unsigned short getcols(void) +unsigned short getcols(int fd) { const unsigned short default_tty = 80; const unsigned short default_notty = 0; unsigned short termwidth = 0; - if(!isatty(fileno(stdout))) { + if(!isatty(fd)) { return default_notty; } -#ifdef TIOCGSIZE +#if defined(TIOCGSIZE) struct ttysize win; - if(ioctl(1, TIOCGSIZE, &win) == 0) { + if(ioctl(fd, TIOCGSIZE, &win) == 0) { termwidth = win.ts_cols; } #elif defined(TIOCGWINSZ) struct winsize win; - if(ioctl(1, TIOCGWINSZ, &win) == 0) { + if(ioctl(fd, TIOCGWINSZ, &win) == 0) { termwidth = win.ws_col; } #endif @@ -256,12 +254,11 @@ char *mdirname(const char *path) /* output a string, but wrap words properly with a specified indentation */ -void indentprint(const char *str, size_t indent) +void indentprint(const char *str, unsigned short indent, unsigned short cols) { wchar_t *wcstr; const wchar_t *p; int len, cidx; - const unsigned short cols = getcols(); if(!str) { return; @@ -270,7 +267,7 @@ void indentprint(const char *str, size_t indent) /* if we're not a tty, or our tty is not wide enough that wrapping even makes * sense, print without indenting */ if(cols == 0 || indent > cols) { - printf("%s", str); + fputs(str, stdout); return; } @@ -318,13 +315,13 @@ void indentprint(const char *str, size_t indent) /* Trim whitespace and newlines from a string */ -char *strtrim(char *str) +size_t strtrim(char *str) { - char *pch = str; + char *end, *pch = str; if(str == NULL || *str == '\0') { /* string is empty, so we're done. */ - return str; + return 0; } while(isspace((unsigned char)*pch)) { @@ -341,16 +338,16 @@ char *strtrim(char *str) /* check if there wasn't anything but whitespace in the string. */ if(*str == '\0') { - return str; + return 0; } - pch = (str + (strlen(str) - 1)); - while(isspace((unsigned char)*pch)) { - pch--; + end = (str + strlen(str) - 1); + while(isspace((unsigned char)*end)) { + end--; } - *++pch = '\0'; + *++end = '\0'; - return str; + return end - pch; } /* Replace all occurances of 'needle' with 'replace' in 'str', returning @@ -391,7 +388,7 @@ char *strreplace(const char *str, const char *needle, const char *replace) p = str; newp = newstr; for(i = list; i; i = alpm_list_next(i)) { - q = alpm_list_getdata(i); + q = i->data; if(q > p) { /* add chars between this occurence and last occurence, if any */ memcpy(newp, p, (size_t)(q - p)); @@ -463,7 +460,7 @@ static size_t string_length(const char *s) return len; } -void string_display(const char *title, const char *string) +void string_display(const char *title, const char *string, unsigned short cols) { if(title) { printf("%s ", title); @@ -473,82 +470,128 @@ void string_display(const char *title, const char *string) } else { /* compute the length of title + a space */ size_t len = string_length(title) + 1; - indentprint(string, len); + indentprint(string, (unsigned short)len, cols); } printf("\n"); } -static void table_print_line(const alpm_list_t *line, - size_t colcount, size_t *widths) +static void table_print_line(const alpm_list_t *line, short col_padding, + size_t colcount, size_t *widths, int *has_data) { - size_t i; + size_t i, lastcol = 0; + int need_padding = 0; const alpm_list_t *curcell; + for(i = colcount; i > 0; i--) { + if(has_data[i - 1]) { + lastcol = i - 1; + break; + } + } + for(i = 0, curcell = line; curcell && i < colcount; i++, curcell = alpm_list_next(curcell)) { - const char *value = curcell->data; - size_t len = string_length(value); + const char *value; + int cell_padding; + + if(!has_data[i]) { + continue; + } + + value = curcell->data; + if(!value) { + value = ""; + } /* silly printf requires padding size to be an int */ - int padding = (int)widths[i] - (int)len; - if(padding < 0) { - padding = 0; + cell_padding = (int)widths[i] - (int)string_length(value); + if(cell_padding < 0) { + cell_padding = 0; + } + if(need_padding) { + printf("%*s", col_padding, ""); } /* left-align all but the last column */ - if(i + 1 < colcount) { - printf("%s%*s", value, padding, ""); + if(i != lastcol) { + printf("%s%*s", value, cell_padding, ""); } else { - printf("%*s%s", padding, "", value); + printf("%*s%s", cell_padding, "", value); } + need_padding = 1; } printf("\n"); } -/* find the max string width of each column */ + + +/** + * Find the max string width of each column. Also determines whether values + * exist in the column and sets the value in has_data accordingly. + * @param header a list of header strings + * @param rows a list of lists of rows as strings + * @param padding the amount of padding between columns + * @param totalcols the total number of columns in the header and each row + * @param widths a pointer to store width data + * @param has_data a pointer to store whether column has data + * + * @return the total width of the table; 0 on failure + */ static size_t table_calc_widths(const alpm_list_t *header, - const alpm_list_t *rows, size_t totalcols, size_t **widths) + const alpm_list_t *rows, short padding, size_t totalcols, + size_t **widths, int **has_data) { const alpm_list_t *i; - const unsigned short padding = 2; - size_t curcol, totalwidth = 0; + size_t curcol, totalwidth = 0, usefulcols = 0; size_t *colwidths; + int *coldata; if(totalcols <= 0) { return 0; } colwidths = malloc(totalcols * sizeof(size_t)); - if(!colwidths) { + coldata = calloc(totalcols, sizeof(int)); + if(!colwidths || !coldata) { return 0; } /* header determines column count and initial values of longest_strs */ for(i = header, curcol = 0; i; i = alpm_list_next(i), curcol++) { - colwidths[curcol] = string_length(alpm_list_getdata(i)); + colwidths[curcol] = string_length(i->data); + /* note: header does not determine whether column has data */ } /* now find the longest string in each column */ for(i = rows; i; i = alpm_list_next(i)) { /* grab first column of each row and iterate through columns */ - const alpm_list_t *j = alpm_list_getdata(i); + const alpm_list_t *j = i->data; for(curcol = 0; j; j = alpm_list_next(j), curcol++) { - char *str = alpm_list_getdata(j); + const char *str = j->data; size_t str_len = string_length(str); if(str_len > colwidths[curcol]) { colwidths[curcol] = str_len; } + if(str_len > 0) { + coldata[curcol] = 1; + } } } for(i = header, curcol = 0; i; i = alpm_list_next(i), curcol++) { - /* pad everything but the last column */ - if(curcol + 1 < totalcols) { - colwidths[curcol] += padding; + /* only include columns that have data */ + if(coldata[curcol]) { + usefulcols++; + totalwidth += colwidths[curcol]; } - totalwidth += colwidths[curcol]; + } + + /* add padding between columns */ + if(usefulcols > 0) { + totalwidth += padding * (usefulcols - 1); } *widths = colwidths; + *has_data = coldata; return totalwidth; } @@ -559,28 +602,31 @@ static size_t table_calc_widths(const alpm_list_t *header, * of headers * @param rows the rows to display as a list of lists of strings. the outer * list represents the rows, the inner list the cells (= columns) - * + * @param cols the number of columns available in the terminal * @return -1 if not enough terminal cols available, else 0 */ -int table_display(const char *title, const alpm_list_t *header, - const alpm_list_t *rows) +static int table_display(const char *title, const alpm_list_t *header, + const alpm_list_t *rows, unsigned short cols) { + const unsigned short padding = 2; const alpm_list_t *i; size_t *widths = NULL, totalcols, totalwidth; + int *has_data = NULL; if(rows == NULL || header == NULL) { return 0; } totalcols = alpm_list_count(header); - totalwidth = table_calc_widths(header, rows, totalcols, &widths); + totalwidth = table_calc_widths(header, rows, padding, totalcols, + &widths, &has_data); /* return -1 if terminal is not wide enough */ - if(totalwidth > getcols()) { + if(totalwidth > cols) { pm_printf(ALPM_LOG_WARNING, _("insufficient columns available for table display\n")); return -1; } - if(!totalwidth || !widths) { + if(!totalwidth || !widths || !has_data) { return -1; } @@ -588,18 +634,20 @@ int table_display(const char *title, const alpm_list_t *header, printf("%s\n\n", title); } - table_print_line(header, totalcols, widths); + table_print_line(header, padding, totalcols, widths, has_data); printf("\n"); for(i = rows; i; i = alpm_list_next(i)) { - table_print_line(alpm_list_getdata(i), totalcols, widths); + table_print_line(i->data, padding, totalcols, widths, has_data); } free(widths); + free(has_data); return 0; } -void list_display(const char *title, const alpm_list_t *list) +void list_display(const char *title, const alpm_list_t *list, + unsigned short maxcols) { const alpm_list_t *i; size_t len = 0; @@ -612,20 +660,19 @@ void list_display(const char *title, const alpm_list_t *list) if(!list) { printf("%s\n", _("None")); } else { - const unsigned short maxcols = getcols(); size_t cols = len; - const char *str = alpm_list_getdata(list); - printf("%s", str); + const char *str = list->data; + fputs(str, stdout); cols += string_length(str); for(i = alpm_list_next(list); i; i = alpm_list_next(i)) { - str = alpm_list_getdata(i); + str = i->data; size_t s = string_length(str); /* wrap only if we have enough usable column space */ if(maxcols > len && cols + s + 2 >= maxcols) { size_t j; cols = len; printf("\n"); - for (j = 1; j <= len; j++) { + for(j = 1; j <= len; j++) { printf(" "); } } else if(cols != len) { @@ -633,19 +680,20 @@ void list_display(const char *title, const alpm_list_t *list) printf(" "); cols += 2; } - printf("%s", str); + fputs(str, stdout); cols += s; } - printf("\n"); + putchar('\n'); } } -void list_display_linebreak(const char *title, const alpm_list_t *list) +void list_display_linebreak(const char *title, const alpm_list_t *list, + unsigned short maxcols) { - size_t len = 0; + unsigned short len = 0; if(title) { - len = string_length(title) + 1; + len = (unsigned short)string_length(title) + 1; printf("%s ", title); } @@ -654,7 +702,7 @@ void list_display_linebreak(const char *title, const alpm_list_t *list) } else { const alpm_list_t *i; /* Print the first element */ - indentprint((const char *) alpm_list_getdata(list), len); + indentprint((const char *)list->data, len, maxcols); printf("\n"); /* Print the rest */ for(i = alpm_list_next(list); i; i = alpm_list_next(i)) { @@ -662,18 +710,19 @@ void list_display_linebreak(const char *title, const alpm_list_t *list) for(j = 1; j <= len; j++) { printf(" "); } - indentprint((const char *) alpm_list_getdata(i), len); + indentprint((const char *)i->data, len, maxcols); printf("\n"); } } } -void signature_display(const char *title, alpm_siglist_t *siglist) +void signature_display(const char *title, alpm_siglist_t *siglist, + unsigned short maxcols) { - size_t len = 0; + unsigned short len = 0; if(title) { - len = string_length(title) + 1; + len = (unsigned short)string_length(title) + 1; printf("%s ", title); } if(siglist->count == 0) { @@ -737,7 +786,7 @@ void signature_display(const char *title, alpm_siglist_t *siglist) pm_printf(ALPM_LOG_ERROR, _("failed to allocate string\n")); continue; } - indentprint(sigline, len); + indentprint(sigline, len, maxcols); printf("\n"); free(sigline); } @@ -745,7 +794,7 @@ void signature_display(const char *title, alpm_siglist_t *siglist) } /* creates a header row for use with table_display */ -static alpm_list_t *create_verbose_header(int dl_size) +static alpm_list_t *create_verbose_header(void) { alpm_list_t *res = NULL; char *str; @@ -758,16 +807,14 @@ static alpm_list_t *create_verbose_header(int dl_size) res = alpm_list_add(res, str); str = _("Net Change"); res = alpm_list_add(res, str); - if(dl_size) { - str = _("Download Size"); - res = alpm_list_add(res, str); - } + str = _("Download Size"); + res = alpm_list_add(res, str); return res; } /* returns package info as list of strings */ -static alpm_list_t *create_verbose_row(pm_target_t *target, int dl_size) +static alpm_list_t *create_verbose_row(pm_target_t *target) { char *str; off_t size = 0; @@ -777,7 +824,12 @@ static alpm_list_t *create_verbose_row(pm_target_t *target, int dl_size) /* a row consists of the package name, */ if(target->install) { - pm_asprintf(&str, "%s", alpm_pkg_get_name(target->install)); + const alpm_db_t *db = alpm_pkg_get_db(target->install); + if(db) { + pm_asprintf(&str, "%s/%s", alpm_db_get_name(db), alpm_pkg_get_name(target->install)); + } else { + pm_asprintf(&str, "%s", alpm_pkg_get_name(target->install)); + } } else { pm_asprintf(&str, "%s", alpm_pkg_get_name(target->remove)); } @@ -799,16 +851,14 @@ static alpm_list_t *create_verbose_row(pm_target_t *target, int dl_size) pm_asprintf(&str, "%.2f %s", human_size, label); ret = alpm_list_add(ret, str); - if(dl_size) { - size = target->install ? alpm_pkg_download_size(target->install) : 0; + size = target->install ? alpm_pkg_download_size(target->install) : 0; + if(size != 0) { human_size = humanize_size(size, 'M', 2, &label); - if(size != 0) { - pm_asprintf(&str, "%.2f %s", human_size, label); - } else { - str = strdup(""); - } - ret = alpm_list_add(ret, str); + pm_asprintf(&str, "%.2f %s", human_size, label); + } else { + str = NULL; } + ret = alpm_list_add(ret, str); return ret; } @@ -820,8 +870,8 @@ static void _display_targets(alpm_list_t *targets, int verbose) const char *label; double size; off_t isize = 0, rsize = 0, dlsize = 0; + unsigned short cols; alpm_list_t *i, *rows = NULL, *names = NULL; - int show_dl_size = config->op == PM_OP_SYNC; if(!targets) { return; @@ -829,7 +879,7 @@ static void _display_targets(alpm_list_t *targets, int verbose) /* gather package info */ for(i = targets; i; i = alpm_list_next(i)) { - pm_target_t *target = alpm_list_getdata(i); + pm_target_t *target = i->data; if(target->install) { dlsize += alpm_pkg_download_size(target->install); @@ -845,7 +895,7 @@ static void _display_targets(alpm_list_t *targets, int verbose) for(i = targets; i; i = alpm_list_next(i)) { pm_target_t *target = i->data; - rows = alpm_list_add(rows, create_verbose_row(target, show_dl_size)); + rows = alpm_list_add(rows, create_verbose_row(target)); if(target->install) { pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(target->install), alpm_pkg_get_version(target->install)); @@ -861,23 +911,24 @@ static void _display_targets(alpm_list_t *targets, int verbose) /* print to screen */ pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets)); - printf("\n"); + + cols = getcols(fileno(stdout)); if(verbose) { - alpm_list_t *header = create_verbose_header(show_dl_size); - if(table_display(str, header, rows) != 0) { + alpm_list_t *header = create_verbose_header(); + if(table_display(str, header, rows, cols) != 0) { /* fallback to list display if table wouldn't fit */ - list_display(str, names); + list_display(str, names, cols); } alpm_list_free(header); } else { - list_display(str, names); + list_display(str, names, cols); } printf("\n"); /* rows is a list of lists of strings, free inner lists here */ for(i = rows; i; i = alpm_list_next(i)) { - alpm_list_t *lp = alpm_list_getdata(i); + alpm_list_t *lp = i->data; FREELIST(lp); } alpm_list_free(rows); @@ -931,10 +982,10 @@ static int pkg_cmp(const void *p1, const void *p2) void display_targets(void) { alpm_list_t *i, *targets = NULL; - alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + alpm_db_t *db_local = alpm_get_localdb(config->handle); for(i = alpm_trans_get_add(config->handle); i; i = alpm_list_next(i)) { - alpm_pkg_t *pkg = alpm_list_getdata(i); + alpm_pkg_t *pkg = i->data; pm_target_t *targ = calloc(1, sizeof(pm_target_t)); if(!targ) return; targ->install = pkg; @@ -945,7 +996,7 @@ void display_targets(void) targets = alpm_list_add(targets, targ); } for(i = alpm_trans_get_remove(config->handle); i; i = alpm_list_next(i)) { - alpm_pkg_t *pkg = alpm_list_getdata(i); + alpm_pkg_t *pkg = i->data; pm_target_t *targ = calloc(1, sizeof(pm_target_t)); if(!targ) return; targ->remove = pkg; @@ -980,7 +1031,7 @@ static char *pkg_get_location(alpm_pkg_t *pkg) case PM_OP_SYNC: servers = alpm_db_get_servers(alpm_pkg_get_db(pkg)); if(servers) { - pm_asprintf(&string, "%s/%s", alpm_list_getdata(servers), + pm_asprintf(&string, "%s/%s", servers->data, alpm_pkg_get_filename(pkg)); return string; } @@ -1054,7 +1105,7 @@ void print_packages(const alpm_list_t *packages) config->print_format = strdup("%l"); } for(i = packages; i; i = alpm_list_next(i)) { - alpm_pkg_t *pkg = alpm_list_getdata(i); + alpm_pkg_t *pkg = i->data; char *string = strdup(config->print_format); char *temp = string; /* %n : pkgname */ @@ -1096,46 +1147,104 @@ void print_packages(const alpm_list_t *packages) free(size); free(temp); } - printf("%s\n",string); + printf("%s\n", string); free(string); } } -/* Helper function for comparing strings using the - * alpm "compare func" signature */ -int str_cmp(const void *s1, const void *s2) +/** + * Helper function for comparing depends using the alpm "compare func" + * signature. The function descends through the structure in the following + * comparison order: name, modifier (e.g., '>', '='), version, description. + * @param d1 the first depend structure + * @param d2 the second depend structure + * @return -1, 0, or 1 if first is <, ==, or > second + */ +static int depend_cmp(const void *d1, const void *d2) { - return strcmp(s1, s2); + const alpm_depend_t *dep1 = d1; + const alpm_depend_t *dep2 = d2; + int ret; + + ret = strcmp(dep1->name, dep2->name); + if(ret == 0) { + ret = dep1->mod - dep2->mod; + } + if(ret == 0) { + if(dep1->version && dep2->version) { + ret = strcmp(dep1->version, dep2->version); + } else if(!dep1->version && dep2->version) { + ret = -1; + } else if(dep1->version && !dep2->version) { + ret = 1; + } + } + if(ret == 0) { + if(dep1->desc && dep2->desc) { + ret = strcmp(dep1->desc, dep2->desc); + } else if(!dep1->desc && dep2->desc) { + ret = -1; + } else if(dep1->desc && !dep2->desc) { + ret = 1; + } + } + + return ret; } void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg) { - alpm_list_t *old = alpm_pkg_get_optdepends(oldpkg); - alpm_list_t *new = alpm_pkg_get_optdepends(newpkg); - alpm_list_t *optdeps = alpm_list_diff(new,old,str_cmp); - if(optdeps) { + alpm_list_t *i, *old, *new, *optdeps, *optstrings = NULL; + + old = alpm_pkg_get_optdepends(oldpkg); + new = alpm_pkg_get_optdepends(newpkg); + optdeps = alpm_list_diff(new, old, depend_cmp); + + /* turn optdepends list into a text list */ + for(i = optdeps; i; i = alpm_list_next(i)) { + alpm_depend_t *optdep = i->data; + optstrings = alpm_list_add(optstrings, alpm_dep_compute_string(optdep)); + } + + if(optstrings) { printf(_("New optional dependencies for %s\n"), alpm_pkg_get_name(newpkg)); - list_display_linebreak(" ", optdeps); + unsigned short cols = getcols(fileno(stdout)); + list_display_linebreak(" ", optstrings, cols); } + alpm_list_free(optdeps); + FREELIST(optstrings); } void display_optdepends(alpm_pkg_t *pkg) { - alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg); - if(optdeps) { + alpm_list_t *i, *optdeps, *optstrings = NULL; + + optdeps = alpm_pkg_get_optdepends(pkg); + + /* turn optdepends list into a text list */ + for(i = optdeps; i; i = alpm_list_next(i)) { + alpm_depend_t *optdep = i->data; + optstrings = alpm_list_add(optstrings, alpm_dep_compute_string(optdep)); + } + + if(optstrings) { printf(_("Optional dependencies for %s\n"), alpm_pkg_get_name(pkg)); - list_display_linebreak(" ", optdeps); + unsigned short cols = getcols(fileno(stdout)); + list_display_linebreak(" ", optstrings, cols); } + + FREELIST(optstrings); } -static void display_repo_list(const char *dbname, alpm_list_t *list) +static void display_repo_list(const char *dbname, alpm_list_t *list, + unsigned short cols) { const char *prefix= " "; printf(":: "); printf(_("Repository %s\n"), dbname); - list_display(prefix, list); + list_display(prefix, list, cols); } void select_display(const alpm_list_t *pkglist) @@ -1145,15 +1254,16 @@ void select_display(const alpm_list_t *pkglist) alpm_list_t *list = NULL; char *string = NULL; const char *dbname = NULL; + unsigned short cols = getcols(fileno(stdout)); - for (i = pkglist; i; i = i->next) { - alpm_pkg_t *pkg = alpm_list_getdata(i); + for(i = pkglist; i; i = i->next) { + alpm_pkg_t *pkg = i->data; alpm_db_t *db = alpm_pkg_get_db(pkg); if(!dbname) dbname = alpm_db_get_name(db); if(strcmp(alpm_db_get_name(db), dbname) != 0) { - display_repo_list(dbname, list); + display_repo_list(dbname, list, cols); FREELIST(list); dbname = alpm_db_get_name(db); } @@ -1162,7 +1272,7 @@ void select_display(const alpm_list_t *pkglist) list = alpm_list_add(list, string); nth++; } - display_repo_list(dbname, list); + display_repo_list(dbname, list, cols); FREELIST(list); } @@ -1189,17 +1299,17 @@ static int multiselect_parse(char *array, int count, char *response) { char *str, *saveptr; - for (str = response; ; str = NULL) { + for(str = response; ; str = NULL) { int include = 1; int start, end; + size_t len; char *ends = NULL; char *starts = strtok_r(str, " ", &saveptr); if(starts == NULL) { break; } - strtrim(starts); - int len = strlen(starts); + len = strtrim(starts); if(len == 0) continue; @@ -1274,10 +1384,11 @@ int multiselect_question(char *array, int count) break; } - flush_term_input(); + flush_term_input(fileno(stdin)); if(fgets(response, response_len, stdin)) { const size_t response_incr = 64; + size_t len; /* handle buffer not being large enough to read full line case */ while(*lastchar == '\0' && lastchar[-1] != '\n') { response_len += response_incr; @@ -1294,8 +1405,9 @@ int multiselect_question(char *array, int count) return -1; } } - strtrim(response); - if(strlen(response) > 0) { + + len = strtrim(response); + if(len > 0) { if(multiselect_parse(array, count, response) == -1) { /* only loop if user gave an invalid answer */ continue; @@ -1335,11 +1447,11 @@ int select_question(int count) break; } - flush_term_input(); + flush_term_input(fileno(stdin)); if(fgets(response, sizeof(response), stdin)) { - strtrim(response); - if(strlen(response) > 0) { + size_t len = strtrim(response); + if(len > 0) { int n; if(parseindex(response, &n, 1, count) != 0) continue; @@ -1358,6 +1470,7 @@ static int question(short preset, char *fmt, va_list args) { char response[32]; FILE *stream; + int fd_in = fileno(stdin); if(config->noconfirm) { stream = stdout; @@ -1384,17 +1497,17 @@ static int question(short preset, char *fmt, va_list args) } fflush(stream); - flush_term_input(); + flush_term_input(fd_in); if(fgets(response, sizeof(response), stdin)) { - strtrim(response); - if(strlen(response) == 0) { + size_t len = strtrim(response); + if(len == 0) { return preset; } /* if stdin is piped, response does not get printed out, and as a result * a \n is missing, resulting in broken output (FS#27909) */ - if(!isatty(fileno(stdin))) { + if(!isatty(fd_in)) { fprintf(stream, "%s\n", response); } diff --git a/src/pacman/util.h b/src/pacman/util.h index 5ccd480a..0dfdc851 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -36,9 +36,6 @@ #define _n(str1, str2, ct) (ct == 1 ? str1 : str2) #endif -/* update speed for the fill_progress based functions */ -#define UPDATE_SPEED_SEC 0.2f - typedef struct _pm_target_t { alpm_pkg_t *remove; alpm_pkg_t *install; @@ -50,21 +47,23 @@ int trans_init(alpm_transflag_t flags, int check_valid); int trans_release(void); int needs_root(void); int check_syncdbs(size_t need_repos, int check_valid); -unsigned short getcols(void); +unsigned short getcols(int fd); int rmrf(const char *path); const char *mbasename(const char *path); char *mdirname(const char *path); -void indentprint(const char *str, size_t indent); -char *strtrim(char *str); +void indentprint(const char *str, unsigned short indent, unsigned short cols); +size_t strtrim(char *str); char *strreplace(const char *str, const char *needle, const char *replace); alpm_list_t *strsplit(const char *str, const char splitchar); -void string_display(const char *title, const char *string); +void string_display(const char *title, const char *string, unsigned short cols); double humanize_size(off_t bytes, const char target_unit, int precision, const char **label); -int table_display(const char *title, const alpm_list_t *header, const alpm_list_t *rows); -void list_display(const char *title, const alpm_list_t *list); -void list_display_linebreak(const char *title, const alpm_list_t *list); -void signature_display(const char *title, alpm_siglist_t *siglist); +void list_display(const char *title, const alpm_list_t *list, + unsigned short maxcols); +void list_display_linebreak(const char *title, const alpm_list_t *list, + unsigned short maxcols); +void signature_display(const char *title, alpm_siglist_t *siglist, + unsigned short maxcols); void display_targets(void); int str_cmp(const void *s1, const void *s2); void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg); diff --git a/src/util/Makefile.am b/src/util/Makefile.am index e4af56cf..e386d950 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -1,17 +1,21 @@ # paths set at make time conffile = ${sysconfdir}/pacman.conf dbpath = ${localstatedir}/lib/pacman/ +gpgdir = ${sysconfdir}/pacman.d/gnupg/ cachedir = ${localstatedir}/cache/pacman/pkg/ bin_PROGRAMS = vercmp testpkg testdb cleanupdelta pacsort pactree DEFS = -DLOCALEDIR=\"@localedir@\" \ -DCONFFILE=\"$(conffile)\" \ - -DROOTDIR=\"$(ROOTDIR)\" \ -DDBPATH=\"$(dbpath)\" \ + -DGPGDIR=\"$(gpgdir)\" \ -DCACHEDIR=\"$(cachedir)\" \ @DEFS@ -INCLUDES = -I$(top_srcdir)/lib/libalpm + +AM_CPPFLAGS = \ + -imacros $(top_builddir)/config.h \ + -I$(top_srcdir)/lib/libalpm AM_CFLAGS = -pedantic -D_GNU_SOURCE diff --git a/src/util/cleanupdelta.c b/src/util/cleanupdelta.c index 6553e6f6..2f7720b5 100644 --- a/src/util/cleanupdelta.c +++ b/src/util/cleanupdelta.c @@ -17,8 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -56,10 +54,10 @@ static void checkpkgs(alpm_list_t *pkglist) { alpm_list_t *i, *j; for(i = pkglist; i; i = alpm_list_next(i)) { - alpm_pkg_t *pkg = alpm_list_getdata(i); + alpm_pkg_t *pkg = i->data; alpm_list_t *unused = alpm_pkg_unused_deltas(pkg); for(j = unused; j; j = alpm_list_next(j)) { - char *delta = alpm_list_getdata(j); + const char *delta = j->data; printf("%s\n", delta); } alpm_list_free(unused); @@ -72,8 +70,8 @@ static void checkdbs(alpm_list_t *dbnames) { const alpm_siglevel_t level = ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; for(i = dbnames; i; i = alpm_list_next(i)) { - const char *dbname = alpm_list_getdata(i); - db = alpm_db_register_sync(handle, dbname, level); + const char *dbname = i->data; + db = alpm_register_syncdb(handle, dbname, level); if(db == NULL) { fprintf(stderr, "error: could not register sync database '%s' (%s)\n", dbname, alpm_strerror(alpm_errno(handle))); @@ -94,7 +92,7 @@ static void usage(void) { int main(int argc, char *argv[]) { const char *dbpath = DBPATH; - enum _alpm_errno_t err; + alpm_errno_t err; int a = 1; alpm_list_t *dbnames = NULL; diff --git a/src/util/pacsort.c b/src/util/pacsort.c index 0eedf59d..7275cc77 100644 --- a/src/util/pacsort.c +++ b/src/util/pacsort.c @@ -17,8 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <errno.h> #include <getopt.h> #include <stdio.h> diff --git a/src/util/pactree.c b/src/util/pactree.c index cee5433a..aa02c808 100644 --- a/src/util/pactree.c +++ b/src/util/pactree.c @@ -17,8 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <ctype.h> #include <getopt.h> #include <stdio.h> @@ -119,13 +117,13 @@ char *strndup(const char *s, size_t n) } #endif -static char *strtrim(char *str) +static size_t strtrim(char *str) { - char *pch = str; + char *end, *pch = str; if(str == NULL || *str == '\0') { /* string is empty, so we're done. */ - return str; + return 0; } while(isspace((unsigned char)*pch)) { @@ -142,21 +140,21 @@ static char *strtrim(char *str) /* check if there wasn't anything but whitespace in the string. */ if(*str == '\0') { - return str; + return 0; } - pch = (str + (strlen(str) - 1)); - while(isspace((unsigned char)*pch)) { - pch--; + end = (str + strlen(str) - 1); + while(isspace((unsigned char)*end)) { + end--; } - *++pch = '\0'; + *++end = '\0'; - return str; + return end - pch; } static int register_syncs(void) { FILE *fp; - char *ptr, *section = NULL; + char *section = NULL; char line[LINE_MAX]; const alpm_siglevel_t level = ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; @@ -167,23 +165,26 @@ static int register_syncs(void) { } while(fgets(line, LINE_MAX, fp)) { + size_t linelen; + char *ptr; + /* ignore whole line and end of line comments */ if((ptr = strchr(line, '#'))) { *ptr = '\0'; } - strtrim(line); + linelen = strtrim(line); - if(strlen(line) == 0) { + if(linelen == 0) { continue; } - if(line[0] == '[' && line[strlen(line) - 1] == ']') { + if(line[0] == '[' && line[linelen - 1] == ']') { free(section); - section = strndup(&line[1], strlen(line) - 2); + section = strndup(&line[1], linelen - 2); if(section && strcmp(section, "options") != 0) { - alpm_db_register_sync(handle, section, level); + alpm_register_syncdb(handle, section, level); } } } @@ -363,7 +364,7 @@ static alpm_pkg_t *get_pkg_from_dbs(alpm_list_t *dbs, const char *needle) { alpm_pkg_t *ret; for(i = dbs; i; i = alpm_list_next(i)) { - ret = alpm_db_get_pkg(alpm_list_getdata(i), needle); + ret = alpm_db_get_pkg(i->data, needle); if(ret) { return ret; } @@ -386,7 +387,7 @@ static void walk_reverse_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, int depth) required_by = alpm_pkg_compute_requiredby(pkg); for(i = required_by; i; i = alpm_list_next(i)) { - const char *pkgname = alpm_list_getdata(i); + const char *pkgname = i->data; if(alpm_list_find_str(walked, pkgname)) { /* if we've already seen this package, don't print in "unique" output @@ -417,7 +418,7 @@ static void walk_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, int depth) walked = alpm_list_add(walked, (void *)alpm_pkg_get_name(pkg)); for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { - alpm_depend_t *depend = alpm_list_getdata(i); + alpm_depend_t *depend = i->data; alpm_pkg_t *provider = alpm_find_dbs_satisfier(handle, dblist, depend->name); if(provider) { @@ -443,7 +444,7 @@ static void walk_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, int depth) int main(int argc, char *argv[]) { int freelist = 0, ret = 0; - enum _alpm_errno_t err; + alpm_errno_t err; const char *target_name; alpm_pkg_t *pkg; alpm_list_t *dblist = NULL; @@ -467,9 +468,9 @@ int main(int argc, char *argv[]) ret = 1; goto finish; } - dblist = alpm_option_get_syncdbs(handle); + dblist = alpm_get_syncdbs(handle); } else { - dblist = alpm_list_add(dblist, alpm_option_get_localdb(handle)); + dblist = alpm_list_add(dblist, alpm_get_localdb(handle)); freelist = 1; } diff --git a/src/util/testdb.c b/src/util/testdb.c index d85687a4..f3a7b659 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -17,8 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "config.h" - #include <unistd.h> #include <stdio.h> #include <stdlib.h> @@ -94,17 +92,16 @@ static int check_localdb_files(void) return ret; } -static int checkdeps(alpm_list_t *pkglist) +static int check_deps(alpm_list_t *pkglist) { alpm_list_t *data, *i; int ret = 0; /* check dependencies */ data = alpm_checkdeps(handle, pkglist, NULL, pkglist, 0); for(i = data; i; i = alpm_list_next(i)) { - alpm_depmissing_t *miss = alpm_list_getdata(i); + alpm_depmissing_t *miss = i->data; char *depstring = alpm_dep_compute_string(miss->depend); - printf("missing dependency for %s : %s\n", miss->target, - depstring); + printf("missing %s dependency for %s\n", depstring, miss->target); free(depstring); ret++; } @@ -112,14 +109,14 @@ static int checkdeps(alpm_list_t *pkglist) return ret; } -static int checkconflicts(alpm_list_t *pkglist) +static int check_conflicts(alpm_list_t *pkglist) { alpm_list_t *data, *i; int ret = 0; /* check conflicts */ data = alpm_checkconflicts(handle, pkglist); for(i = data; i; i = i->next) { - alpm_conflict_t *conflict = alpm_list_getdata(i); + alpm_conflict_t *conflict = i->data; printf("%s conflicts with %s\n", conflict->package1, conflict->package2); ret++; @@ -128,6 +125,77 @@ static int checkconflicts(alpm_list_t *pkglist) return ret; } +struct fileitem { + alpm_file_t *file; + alpm_pkg_t *pkg; +}; + +static int fileitem_cmp(const void *p1, const void *p2) +{ + const struct fileitem * fi1 = p1; + const struct fileitem * fi2 = p2; + return strcmp(fi1->file->name, fi2->file->name); +} + +static int check_filelists(alpm_list_t *pkglist) +{ + alpm_list_t *i; + int ret = 0; + size_t list_size = 4096; + size_t offset = 0, j; + struct fileitem *all_files; + struct fileitem *prev_fileitem = NULL; + + all_files = malloc(list_size * sizeof(struct fileitem)); + + for(i = pkglist; i; i = i->next) { + alpm_pkg_t *pkg = i->data; + alpm_filelist_t *filelist = alpm_pkg_get_files(pkg); + for(j = 0; j < filelist->count; j++) { + alpm_file_t *file = filelist->files + j; + /* only add files, not directories, to our big list */ + if(file->name[strlen(file->name) - 1] == '/') { + continue; + } + + /* do we need to reallocate and grow our array? */ + if(offset >= list_size) { + struct fileitem *new_files; + new_files = realloc(all_files, list_size * 2 * sizeof(struct fileitem)); + if(!new_files) { + free(all_files); + return 1; + } + all_files = new_files; + list_size *= 2; + } + + /* we can finally add it to the list */ + all_files[offset].file = file; + all_files[offset].pkg = pkg; + offset++; + } + } + + /* now sort the list so we can find duplicates */ + qsort(all_files, offset, sizeof(struct fileitem), fileitem_cmp); + + /* do a 'uniq' style check on the list */ + for(j = 0; j < offset; j++) { + struct fileitem *fileitem = all_files + j; + if(prev_fileitem && fileitem_cmp(prev_fileitem, fileitem) == 0) { + printf("file owned by %s and %s: %s\n", + alpm_pkg_get_name(prev_fileitem->pkg), + alpm_pkg_get_name(fileitem->pkg), + fileitem->file->name); + } + prev_fileitem = fileitem; + } + + free(all_files); + return ret; +} + static int check_localdb(void) { int ret = 0; @@ -139,10 +207,11 @@ static int check_localdb(void) return ret; } - db = alpm_option_get_localdb(handle); + db = alpm_get_localdb(handle); pkglist = alpm_db_get_pkgcache(db); - ret += checkdeps(pkglist); - ret += checkconflicts(pkglist); + ret += check_deps(pkglist); + ret += check_conflicts(pkglist); + ret += check_filelists(pkglist); return ret; } @@ -154,8 +223,8 @@ static int check_syncdbs(alpm_list_t *dbnames) const alpm_siglevel_t level = ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; for(i = dbnames; i; i = alpm_list_next(i)) { - char *dbname = alpm_list_getdata(i); - db = alpm_db_register_sync(handle, dbname, level); + const char *dbname = i->data; + db = alpm_register_syncdb(handle, dbname, level); if(db == NULL) { fprintf(stderr, "error: could not register sync database (%s)\n", alpm_strerror(alpm_errno(handle))); @@ -165,7 +234,7 @@ static int check_syncdbs(alpm_list_t *dbnames) pkglist = alpm_db_get_pkgcache(db); syncpkglist = alpm_list_join(syncpkglist, alpm_list_copy(pkglist)); } - ret += checkdeps(syncpkglist); + ret += check_deps(syncpkglist); cleanup: alpm_list_free(syncpkglist); @@ -185,7 +254,7 @@ static void usage(void) int main(int argc, char *argv[]) { int ret = 0; - enum _alpm_errno_t err; + alpm_errno_t err; const char *dbpath = DBPATH; int a = 1; alpm_list_t *dbnames = NULL; diff --git a/src/util/testpkg.c b/src/util/testpkg.c index 90758e16..96400a75 100644 --- a/src/util/testpkg.c +++ b/src/util/testpkg.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { int retval = 1; /* default = false */ alpm_handle_t *handle; - enum _alpm_errno_t err; + alpm_errno_t err; alpm_pkg_t *pkg = NULL; const alpm_siglevel_t level = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL; @@ -59,6 +59,9 @@ int main(int argc, char *argv[]) /* let us get log messages from libalpm */ alpm_option_set_logcb(handle, output_cb); + /* set gpgdir to default */ + alpm_option_set_gpgdir(handle, GPGDIR); + if(alpm_pkg_load(handle, argv[1], 1, level, &pkg) == -1 || pkg == NULL) { err = alpm_errno(handle); diff --git a/test/pacman/pactest.py b/test/pacman/pactest.py index bb198eb4..2fb64edc 100755 --- a/test/pacman/pactest.py +++ b/test/pacman/pactest.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # pactest : run automated testing on the pacman binary # diff --git a/test/pacman/pmdb.py b/test/pacman/pmdb.py index b94c6cf6..285c3151 100644 --- a/test/pacman/pmdb.py +++ b/test/pacman/pmdb.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # diff --git a/test/pacman/pmenv.py b/test/pacman/pmenv.py index 04aecd9a..0e455cee 100644 --- a/test/pacman/pmenv.py +++ b/test/pacman/pmenv.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # diff --git a/test/pacman/pmfile.py b/test/pacman/pmfile.py index cdcc7715..d5aa1a11 100644 --- a/test/pacman/pmfile.py +++ b/test/pacman/pmfile.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # diff --git a/test/pacman/pmpkg.py b/test/pacman/pmpkg.py index 00f345c0..bfc93dd6 100644 --- a/test/pacman/pmpkg.py +++ b/test/pacman/pmpkg.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # diff --git a/test/pacman/pmrule.py b/test/pacman/pmrule.py index 70c8838e..778b6aac 100644 --- a/test/pacman/pmrule.py +++ b/test/pacman/pmrule.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # @@ -87,8 +87,11 @@ class pmrule(object): if not value in newpkg.depends: success = 0 elif case == "OPTDEPENDS": - if not value in newpkg.optdepends: - success = 0 + success = 0 + for optdep in newpkg.optdepends: + if value == optdep.split(':', 1)[0]: + success = 1 + break elif case == "REASON": if newpkg.reason != int(value): success = 0 diff --git a/test/pacman/pmtest.py b/test/pacman/pmtest.py index 4e1ecd0b..1a026864 100644 --- a/test/pacman/pmtest.py +++ b/test/pacman/pmtest.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # diff --git a/test/pacman/tests/Makefile.am b/test/pacman/tests/Makefile.am index 508534ac..9ab0c777 100644 --- a/test/pacman/tests/Makefile.am +++ b/test/pacman/tests/Makefile.am @@ -17,11 +17,9 @@ edit = sed \ $(CONFTESTS): Makefile - @echo ' ' GEN $@; - @$(RM) $@ $@.tmp - @test -f $(srcdir)/$@.in && $(edit) $(srcdir)/$@.in >$@.tmp || true - @test -f $@.tmp || false - @chmod a-w $@.tmp - @mv $@.tmp $@ + $(AM_V_at)$(RM) $@ $@.tmp + $(AM_V_GEN)test -f $(srcdir)/$@.in && $(edit) $(srcdir)/$@.in >$@.tmp || true + $(AM_V_at)chmod a-w $@.tmp + $(AM_V_at)mv $@.tmp $@ # vim:set ts=2 sw=2 noet: diff --git a/test/pacman/tests/ignore008.py b/test/pacman/tests/ignore008.py new file mode 100644 index 00000000..12416ad9 --- /dev/null +++ b/test/pacman/tests/ignore008.py @@ -0,0 +1,29 @@ +self.description = "Sync with relevant ignored fnmatched packages" + +package1 = pmpkg("foopkg", "1.0-1") +self.addpkg2db("local", package1) + +package2 = pmpkg("barpkg", "2.0-1") +self.addpkg2db("local", package2) + +package3 = pmpkg("bazpkg", "3.0-1") +self.addpkg2db("local", package3) + + +package1up = pmpkg("foopkg", "2.0-1") +self.addpkg2db("sync", package1up) + +package2up = pmpkg("barpkg", "3.0-1") +self.addpkg2db("sync", package2up) + +package3up = pmpkg("bazpkg", "4.0-1") +self.addpkg2db("sync", package3up) + +self.option["IgnorePkg"] = ["foo*", "ba?pkg"] +self.args = "-Su" + + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=foopkg|1.0-1") +self.addrule("PKG_VERSION=barpkg|2.0-1") +self.addrule("PKG_VERSION=bazpkg|3.0-1") diff --git a/test/pacman/tests/remove031.py b/test/pacman/tests/remove031.py new file mode 100644 index 00000000..0ea09c87 --- /dev/null +++ b/test/pacman/tests/remove031.py @@ -0,0 +1,11 @@ +self.description = "Remove a package in HoldPkg" + +p1 = pmpkg("foopkg") +self.addpkg2db("local", p1) + +self.option["HoldPkg"] = ["???pkg"] + +self.args = "-R %s" % p1.name + +self.addrule("PACMAN_RETCODE=1") +self.addrule("PKG_EXIST=foopkg") diff --git a/test/pacman/tests/sync139.py b/test/pacman/tests/sync139.py new file mode 100644 index 00000000..0b0526d8 --- /dev/null +++ b/test/pacman/tests/sync139.py @@ -0,0 +1,23 @@ +self.description = "Sysupgrade of packages in fnmatch'd IgnoreGroup" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.groups = ["grp"] +sp2 = pmpkg("pkg2", "1.0-2") +sp2.groups = ["grp2"] + +for p in sp1, sp2: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1", "1.0-1") +lp2 = pmpkg("pkg2", "1.0-1") + +for p in lp1, lp2: + self.addpkg2db("local", p) + +self.option["IgnoreGroup"] = ["grp"] + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|1.0-1") +self.addrule("PKG_VERSION=pkg2|1.0-2") diff --git a/test/pacman/tests/sync502.py b/test/pacman/tests/sync502.py new file mode 100644 index 00000000..5cc42c9f --- /dev/null +++ b/test/pacman/tests/sync502.py @@ -0,0 +1,17 @@ +self.description = "Install a package from a sync db with fnmatch'ed NoExtract" + +sp = pmpkg("dummy") +sp.files = ["bin/dummy", + "usr/share/man/man8", + "usr/share/man/man1/dummy.1"] +self.addpkg2db("sync", sp) + +self.option["NoExtract"] = ["usr/share/man/*"] + +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/share/man/man8") +self.addrule("!FILE_EXIST=usr/share/man/man1/dummy.1") diff --git a/test/pacman/tests/sync503.py b/test/pacman/tests/sync503.py new file mode 100644 index 00000000..9d24f00d --- /dev/null +++ b/test/pacman/tests/sync503.py @@ -0,0 +1,18 @@ +self.description = "Upgrade a package, with a fnmatch 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.*"] + +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/test/pacman/tests/upgrade012.py b/test/pacman/tests/upgrade012.py index dba8dc18..4d9f0cd1 100644 --- a/test/pacman/tests/upgrade012.py +++ b/test/pacman/tests/upgrade012.py @@ -6,7 +6,7 @@ self.addpkg(p) self.filesystem = ["bin/dummy"] -self.args = "-Uf %s" % p.filename() +self.args = "-U --force %s" % p.filename() self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=dummy") diff --git a/test/pacman/tests/upgrade014.py b/test/pacman/tests/upgrade014.py index 1632dd36..93c2fe2b 100644 --- a/test/pacman/tests/upgrade014.py +++ b/test/pacman/tests/upgrade014.py @@ -13,7 +13,7 @@ p2.files = ["bin/foobar", for p in p1, p2: self.addpkg(p) -self.args = "-Uf %s" % " ".join([p.filename() for p in p1, p2]) +self.args = "-U --force %s" % " ".join([p.filename() for p in p1, p2]) self.addrule("PACMAN_RETCODE=0") for p in p1, p2: diff --git a/test/pacman/tests/upgrade015.py b/test/pacman/tests/upgrade015.py index 22f7c36b..ea6046cb 100644 --- a/test/pacman/tests/upgrade015.py +++ b/test/pacman/tests/upgrade015.py @@ -6,7 +6,7 @@ self.addpkg(p) self.filesystem = ["etc/dummy.conf"] -self.args = "-Uf %s" % p.filename() +self.args = "-U --force %s" % p.filename() self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=dummy") diff --git a/test/pacman/tests/upgrade016.py b/test/pacman/tests/upgrade016.py index dd31c9ab..b6b3f3ae 100644 --- a/test/pacman/tests/upgrade016.py +++ b/test/pacman/tests/upgrade016.py @@ -7,7 +7,7 @@ self.addpkg(p) self.filesystem = ["etc/dummy.conf"] -self.args = "-Uf %s" % p.filename() +self.args = "-U --force %s" % p.filename() self.addrule("PACMAN_RETCODE=0") self.addrule("PKG_EXIST=dummy") diff --git a/test/pacman/tests/upgrade046.py b/test/pacman/tests/upgrade046.py index 12390647..a02a7132 100644 --- a/test/pacman/tests/upgrade046.py +++ b/test/pacman/tests/upgrade046.py @@ -20,7 +20,7 @@ p2.files = ["bin/foobar"] for p in p1, p2: self.addpkg(p) -self.args = "-Uf %s" % " ".join([p.filename() for p in p1, p2]) +self.args = "-U --force %s" % " ".join([p.filename() for p in p1, p2]) self.addrule("PACMAN_RETCODE=0") for p in p1, p2: diff --git a/test/pacman/util.py b/test/pacman/util.py index 81dcc906..d40612dc 100644 --- a/test/pacman/util.py +++ b/test/pacman/util.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # |