diff options
109 files changed, 6399 insertions, 4193 deletions
@@ -35,7 +35,7 @@ while(it) { if(fn) { fn(it->data); } else { - return(1); + return 1; } free(it); it = ptr; @@ -67,11 +67,11 @@ alpm_list_t *alpm_list_add(alpm_list_t *list, void *data) NOT // This is a comment -5. Return statements should be written like a function call. +5. Return statements should *not* be written like function calls. - return(0); - NOT return 0; + NOT + return(0); 6. The sizeof() operator should accept a type, not a value. (TODO: in certain cases, it may be better- should this be a set guideline? Read "The Practice @@ -16,8 +16,8 @@ properly build pacman. libarchive http://code.google.com/p/libarchive/ -libfetch -ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/net/libfetch/README.html +libcurl +http://curl.haxx.se/libcurl/ Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following diff --git a/Makefile.am b/Makefile.am index 32a08f71..259a455b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,6 @@ check-local: test/pacman test/util src/pacman src/util $(PYTHON) $(top_srcdir)/test/pacman/pactest.py --debug=1 \ --test $(top_srcdir)/test/pacman/tests/*.py \ -p $(top_builddir)/src/pacman/pacman - rm -rf $(top_builddir)/root $(SH) $(top_srcdir)/test/util/vercmptest.sh \ $(top_builddir)/src/util/vercmp @@ -192,8 +192,8 @@ remove.c and sync.c). The frontend is using a configuration file, usually "/etc/pacman.conf". Some of these options are only useful for the frontend only (mainly the ones used to -control the output like showsize or totaldownload, or the behavior with -cleanmethod and syncfirst). The rest is used to configure the library. +control the output like totaldownload, or the behavior with cleanmethod and +syncfirst). The rest is used to configure the library. [UPGRADE/REMOVE/SYNC] @@ -10,9 +10,6 @@ Pacman 3.1: Downgrade feature - allow users to see cached packages and downgrade to (previous or any?) available options. -Installed size and download size in -Si/Qi output should scale with package -size- KB to MB to GB. We should also get consistancy of K/KB, M/MB, etc. - Extreme similarity between some of the sync and add code...we have to be able to abstract more away from sync actions and add actions to just 'actions' (example: sync,c, add.c, and deptest.c all contain a switch on PM_DEP_MOD_*). @@ -79,9 +76,6 @@ Refine makepkg error codes. Each kind of failure could have its own code: --failed build --etc. -Add utility function to either frontend or backend to convert sizes: e.g. bytes -to KB, MB, GB. - Revamp the downloadprog function a bit. Seems kind of messy. --print-uri option to sync should not require saying yes or no to up to date diff --git a/configure.ac b/configure.ac index c672c66c..12f36be6 100644 --- a/configure.ac +++ b/configure.ac @@ -93,10 +93,13 @@ AC_ARG_WITH(openssl, AS_HELP_STRING([--with-openssl], [use OpenSSL crypto implementations instead of internal routines]), [], [with_openssl=check]) -# Help line for libfetch -AC_ARG_WITH(fetch, - AS_HELP_STRING([--with-fetch], [use libfetch as an internal downloader]), - [], [with_fetch=check]) +# Help line for using gpgme +AC_ARG_WITH(gpgme, + AS_HELP_STRING([--with-gpgme], [use GPGME for PGP signature verification]), + [], [with_gpgme=check]) + +# Check for useable libcurl +LIBCURL_CHECK_CONFIG([yes], [7.19.4], [with_libcurl=yes], [with_libcurl=no]) # Help line for documentation AC_ARG_ENABLE(doc, @@ -133,6 +136,9 @@ AC_PATH_PROGS([BASH_SHELL], [bash bash4 bash3], [false]) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION(0.13.1) +AC_CHECK_LIB([m], [fabs], , + AC_MSG_ERROR([libm is needed to compile pacman!])) + # Check for libarchive AC_CHECK_LIB([archive], [archive_read_data], , AC_MSG_ERROR([libarchive is needed to compile pacman!])) @@ -145,33 +151,29 @@ AS_IF([test "x$with_openssl" != "xno"], [if test "x$with_openssl" != "xcheck"; then AC_MSG_FAILURE([--with-openssl was given, but -lssl was not found]) fi], - [-lcrypto])], + [-lcrypto]) + with_openssl=$ac_cv_lib_ssl_MD5_Final], AC_MSG_RESULT(no)) -AM_CONDITIONAL([HAVE_LIBSSL], [test "x$ac_cv_lib_ssl_MD5_Final" = "xyes"]) +AM_CONDITIONAL([HAVE_LIBSSL], [test "x$with_openssl" = "xyes"]) -# Enable or disable usage of libfetch -AC_MSG_CHECKING(whether to link with libfetch) -AS_IF([test "x$with_fetch" != "xno"], +# 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([fetch], [fetchParseURL], , - [if test "x$with_fetch" != "xcheck"; then - AC_MSG_FAILURE([--with-fetch was given, but -lfetch was not found]) + 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], - [-lcrypto -ldl]) - # Check if libfetch supports connnection caching which we use - AS_IF([test "x$ac_cv_lib_fetch_fetchParseURL" = "xyes"], - [AC_CHECK_DECL(fetchConnectionCacheInit, , - AC_MSG_ERROR([libfetch must be version 2.28 or greater]), - [#include <fetch.h>]) - ]) - ], + [-lgpgme]) + with_gpgme=$ac_cv_lib_gpgme_gpgme_check_version], AC_MSG_RESULT(no)) -AM_CONDITIONAL([HAVE_LIBFETCH], [test "x$ac_cv_lib_fetch_fetchParseURL" = "xyes"]) +AM_CONDITIONAL([HAVE_LIBGPGME], [test "x$with_gpgme" = "xyes"]) # Checks for header files. AC_CHECK_HEADERS([fcntl.h glob.h libintl.h locale.h mntent.h string.h \ sys/ioctl.h sys/mount.h sys/param.h sys/statvfs.h \ - sys/time.h sys/types.h sys/ucred.h syslog.h wchar.h]) + sys/time.h sys/types.h sys/ucred.h syslog.h termios.h \ + wchar.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE @@ -190,7 +192,7 @@ AC_FUNC_GETMNTENT AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK AC_FUNC_MKTIME AC_CHECK_FUNCS([geteuid getmntinfo realpath regcomp strcasecmp \ - strndup strrchr strsep swprintf \ + strndup strrchr strsep swprintf tcflush \ wcwidth uname]) # For the diskspace code FS_STATS_TYPE @@ -417,6 +419,9 @@ ${PACKAGE_NAME}: build script name : ${BUILDSCRIPT} Compilation options: + Use libcurl : ${with_libcurl} + Use GPGME : ${with_gpgme} + Use OpenSSL : ${with_openssl} Run make in doc/ dir : ${wantdoc} ${asciidoc} Doxygen support : ${usedoxygen} debug support : ${debug} diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 827d9ec0..e9f77940 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -3,8 +3,7 @@ OURSCRIPTS = \ pacdiff \ paclist \ pacscripts \ - pacsearch \ - wget-xdelta.sh + pacsearch OURFILES = \ bash_completion \ @@ -19,7 +18,6 @@ EXTRA_DIST = \ pacscripts.in \ pacsearch.in \ vimprojects \ - wget-xdelta.sh.in \ zsh_completion.in \ README @@ -55,7 +53,6 @@ paclist: $(srcdir)/paclist.in pacscripts: $(srcdir)/pacscripts.in pacsearch: $(srcdir)/pacsearch.in pactree: $(srcdir)/pactree.in -wget-xdelta.sh: $(srcdir)/wget-xdelta.sh.in zsh_completion: $(srcdir)/zsh_completion.in # vim:set ts=2 sw=2 noet: diff --git a/contrib/README b/contrib/README index 4f591012..04b656f3 100644 --- a/contrib/README +++ b/contrib/README @@ -28,6 +28,3 @@ database entries. Useful for reuse, or possible config file extension. vimprojects - a project file for the vim project plugin. -wget-xdelta.sh - A download script for pacman which allows binary deltas -generated with makepkg to be used instead of downloading full binary packages. -This should cut download sizes for some package upgrades significantly. diff --git a/contrib/pacscripts.in b/contrib/pacscripts.in index d3664091..8ad5173b 100755 --- a/contrib/pacscripts.in +++ b/contrib/pacscripts.in @@ -61,7 +61,7 @@ spacman() { if [ $EUID -eq 0 ]; then pacman "$@" else - if [ ! "$(type -p sudo)" ]; then + if ! type -p sudo; then error "Cannot find the sudo binary! Is sudo installed?" error "Otherwise try to run the program as root" exit 1 diff --git a/contrib/wget-xdelta.sh.in b/contrib/wget-xdelta.sh.in deleted file mode 100755 index f2ac1c87..00000000 --- a/contrib/wget-xdelta.sh.in +++ /dev/null @@ -1,70 +0,0 @@ -#!@BASH_SHELL@ - -if [ -r "@sysconfdir@/makepkg.conf" ]; then - source @sysconfdir@/makepkg.conf -else - echo "wget-xdelta: Unable to find makepkg.conf" - exit 1 -fi - -if [ -r ~/.makepkg.conf ]; then - source ~/.makepkg.conf -fi - -out_file=$(basename $1) -file_url=$2 - -if ! [[ "$out_file" =~ "pkg.tar.gz" ]]; then - # If it's not a package file download as normal and exit. - #wget --passive-ftp -c -O "$out_file" "$file_url" - exit $? -fi - - -# Get the package name and version -[[ "$out_file" =~ "$CARCH" ]] && arch="-$CARCH" || arch="" -pkg_data=$(echo $out_file | \ - sed "s|^\(.*\)-\([[:alnum:]_\.]*-[[:alnum:]_\.]*\)${arch}${PKGEXT}.part|\1 \2|") -pkgname=$(echo $pkg_data | cut -d ' ' -f 1) -new_version=$(echo $pkg_data | cut -d ' ' -f 2) -base_url=${file_url%/*} - -# Look for the last version -for file in $(ls -r @localstatedir@/cache/pacman/pkg/${pkgname}-*-*{,-$CARCH}$PKGEXT 2>/dev/null); do - [[ "$file" =~ "$CARCH" ]] && arch="-$CARCH" || arch="" - check_version=$(echo $file | \ - sed "s|^.*/${pkgname}-\([[:alnum:]_\.]*-[[:alnum:]_\.]*\)${arch}$PKGEXT$|\1|" | \ - grep -v "^@localstatedir@/cache/pacman/pkg") - - [ "$check_version" = "" ] && continue - - vercmp=$(vercmp "$check_version" "$old_version") - if [ "$check_version" != "$new_version" -a $vercmp -gt 0 ]; then - old_version=$check_version - old_file=$file - fi -done - -if [ "$old_version" != "" -a "$old_version" != "$new_version" ]; then - # Great, we have a cached file, now calculate a patch name from it - delta_name="$pkgname-${old_version}_to_${new_version}-${CARCH}.delta" - - echo "wget-xdelta: Attempting to download delta $delta_name..." >&2 - if wget --passive-ftp -c "$base_url/$delta_name"; then - echo "wget-xdelta: Applying delta..." - if xdelta patch "$delta_name" "$old_file" "$out_file"; then - echo "wget-xdelta: Delta applied successfully!" - rm "$delta_name" - exit 0 - else - echo "wget-xdelta: Failed to apply delta!" - rm $delta_name - fi - fi - fi - -echo "wget-xdelta: Downloading new package..." -wget --passive-ftp -c -O "$out_file" "$file_url" -exit $? - -# vim:set ts=4 sw=4 noet: diff --git a/doc/.gitignore b/doc/.gitignore index a6f4df7f..a7f33e55 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -3,7 +3,9 @@ libalpm.3 makepkg.8 makepkg.conf.5 pacman.8 +pacman-key.8 pacman.conf.5 +pkgdelta.8 repo-add.8 repo-remove.8 vercmp.8 diff --git a/doc/Makefile.am b/doc/Makefile.am index e8f6df09..4fb57803 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -8,6 +8,8 @@ ASCIIDOC_MANS = \ makepkg.8 \ repo-add.8 \ vercmp.8 \ + pkgdelta.8 \ + pacman-key.8 \ PKGBUILD.5 \ makepkg.conf.5 \ pacman.conf.5 \ @@ -20,6 +22,8 @@ HTML_MANPAGES = \ makepkg.8.html \ repo-add.8.html \ vercmp.8.html \ + pkgdelta.8.html \ + pacman-key.8.html \ PKGBUILD.5.html \ makepkg.conf.5.html \ pacman.conf.5.html \ @@ -41,6 +45,8 @@ EXTRA_DIST = \ makepkg.8.txt \ repo-add.8.txt \ vercmp.8.txt \ + pkgdelta.8.txt \ + pacman-key.8.txt \ PKGBUILD.5.txt \ PKGBUILD-example.txt \ makepkg.conf.5.txt \ @@ -134,6 +140,8 @@ pacman.8 pacman.8.html: pacman.8.txt makepkg.8 makepkg.8.html: makepkg.8.txt repo-add.8 repo-add.8.html: repo-add.8.txt vercmp.8 vercmp.8.html: vercmp.8.txt +pkgdelta.8 pkgdelta.8.html: pkgdelta.8.txt +pacman-key.8 pacman-key.8.html: pacman-key.8.txt PKGBUILD.5 PKGBUILD.5.html: PKGBUILD.5.txt PKGBUILD-example.txt makepkg.conf.5 makepkg.conf.5.html: makepkg.conf.5.txt pacman.conf.5 pacman.conf.5.html: pacman.conf.5.txt diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index c0fa5948..24e1a125 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -16,12 +16,12 @@ PKGBUILD Description ----------- -This manual page is meant to describe general rules about PKGBUILDs. Once a +This manual page describes general rules about PKGBUILDs. Once a PKGBUILD is written, the actual package is built using makepkg and installed with pacman. -NOTE: An example PKGBUILD, useful for reference, is located in '{pkgdatadir}'. -Also located there are other example files such as a ChangeLog and an install +NOTE: An example PKGBUILD, useful for reference, is located in '{pkgdatadir}' +along with other example files such as a ChangeLog and an install script. You can copy the provided PKGBUILD.proto file to a new package build directory and make customizations to suit your needs. @@ -30,33 +30,33 @@ Options and Directives ---------------------- The following is a list of standard options and directives available for use in a PKGBUILD. These are all understood and interpreted by makepkg, and most -will be directly transferred to the built package. +of them will be directly transferred to the built package. If you need to create any custom variables for use in your build process, it is -recommended to name your custom variables with an '_' (underscore) prefix. +recommended to prefix their name with an '_' (underscore). This will prevent any possible name clashes with internal makepkg variables. For example, to store the base kernel version in a variable, use something similar to `$_basekernver`. *pkgname (array)*:: - The name of the package. This has be a unix-friendly name as it will be - used in the package filename. Members of the array are not allowed to start - with hyphens. + Either the name of the package or an array of names for split packages. + Because it will be used in the package filename, this has to be unix-friendly. + Members of the array are not allowed to start with hyphens. *pkgver*:: - The version of the software as released from the author (e.g. '2.7.1'). + The version of the software as released from the author (e.g., '2.7.1'). The variable is not allowed to contain colons or hyphens. *pkgrel*:: This is the release number specific to the Arch Linux release. This allows package maintainers to make updates to the package's configure - flags, for example. A pkgrel of '1' is typically used for each upstream - software release and is incremented for intermediate PKGBUILD updates. The + flags, for example. This is typically set to '1' for each new upstream + software release and incremented for intermediate PKGBUILD updates. The variable is not allowed to contain hyphens. *pkgdesc*:: This should be a brief description of the package and its functionality. - Try to keep the description to one line of text. + Try to keep the description to one line of text and not use the package's name. *epoch*:: Used to force the package to be seen as newer than any previous versions @@ -69,50 +69,49 @@ similar to `$_basekernver`. *url*:: This field contains a URL that is associated with the software being - packaged. This is typically the project's website. + packaged. Typically the project's website. *license (array)*:: This field specifies the license(s) that apply to the package. - Commonly-used licenses are found in '/usr/share/licenses/common'. If you + Commonly used licenses can be found in '/usr/share/licenses/common'. If you see the package's license there, simply reference it in the license - field (e.g. `license=('GPL')`). If the package provides a license not - found in '/usr/share/licenses/common', then you should include the license + field (e.g., `license=('GPL')`). If the package provides a license not + available in '/usr/share/licenses/common', then you should include it in the package itself and set `license=('custom')` or `license=('custom:LicenseName')`. The license should be placed in - '$pkgdir/usr/share/licenses/$pkgname' when building the package. If - multiple licenses are applicable for a package, list all of them: + '$pkgdir/usr/share/licenses/$pkgname/' when building the package. If + multiple licenses are applicable, list all of them: `license=('GPL' 'FDL')`. *install*:: Specifies a special install script that is to be included in the package. This file should reside in the same directory as the PKGBUILD, and will be copied into the package by makepkg. It does not need to be included - in the source array (e.g. `install=pkgname.install`). + in the source array (e.g., `install=pkgname.install`). *changelog*:: Specifies a changelog file that is to be included in the package. This file should reside in the same directory as the PKGBUILD, and will be copied into the package by makepkg. It does not need to be included - in the source array (e.g. `changelog=$pkgname.changelog`). + in the source array (e.g., `changelog=$pkgname.changelog`). *source (array)*:: An array of source files required to build the package. Source files - must either reside in the same directory as the PKGBUILD file, or be a - fully-qualified URL that makepkg will use to download the file. In order - to make the PKGBUILD as useful as possible, use the $pkgname and $pkgver - variables if possible when specifying the download location. Any files - that are compressed will automatically be extracted, unless found in - the noextract array listed below. + must either reside in the same directory as the PKGBUILD, or be a + fully-qualified URL that makepkg can use to download the file. + To make the PKGBUILD as useful as possible, use the `$pkgname` and `$pkgver` + variables if possible when specifying the download location. Compressed files + will be extracted automatically unless found in + the noextract array described below. + -It is also possible to specify an optional filename, which is helpful +It is also possible to change the name of the downloaded file, which is helpful with weird URLs and for handling multiple source files with the same name. The syntax is: `source=('filename::url')`. *noextract (array)*:: An array of filenames corresponding to those from the source array. Files listed here will not be extracted with the rest of the source files. This - is useful for packages which use compressed data which is downloaded but - not necessary to uncompress. + is useful for packages that use compressed data directly. *md5sums (array)*:: This array contains an MD5 hash for every source file specified in the @@ -133,31 +132,36 @@ name. The syntax is: `source=('filename::url')`. example, one could install all KDE packages by installing the 'kde' group. *arch (array)*:: - Defines on which architectures the given package is available (e.g. + Defines on which architectures the given package is available (e.g., `arch=('i686' 'x86_64')`). Packages that contain no architecture specific - files may use arch=('any'). + files should use arch=('any'). *backup (array)*:: - A space-delimited array of filenames, without preceding slashes, that + An array of filenames, without preceding slashes, that should be backed up if the package is removed or upgraded. This is commonly used for packages placing configuration files in /etc. See Handling Config Files in linkman:pacman[8] for more information. *depends (array)*:: - An array of packages that this package depends on to run. Packages in + An array of packages this package depends on to run. Entries in this list should be surrounded with single quotes and contain at least the package name. Entries can also include a version requirement of the form 'name<>version', where <> is one of five comparisons: >= (greater than or equal to), <= (less than or equal to), = (equal to), > (greater than), or < (less than). ++ +If the dependency name appears to be a library (ends with .so), makepkg will +try to find a binary that depends on the library in the built package and +append the version needed by the binary. Appending the version yourself +disables auto detection. *makedepends (array)*:: - An array of packages that this package depends on to build, but are not + An array of packages this package depends on to build but are not needed at runtime. Packages in this list follow the same format as depends. *checkdepends (array)*:: - An array of packages that this package depends on to run its test suite, + An array of packages this package depends on to run its test suite but are not needed at runtime. Packages in this list follow the same format as depends. These dependencies are only considered when the check() function is present and is to be run by makepkg. @@ -177,7 +181,7 @@ name. The syntax is: `source=('filename::url')`. same format as depends. Versioned conflicts are also supported. *provides (array)*:: - An array of ``virtual provisions'' that this package provides. This allows + An array of ``virtual provisions'' this package provides. This allows a package to provide dependencies other than its own package name. For example, the dcron package can provide 'cron', which allows packages to depend on 'cron' rather than 'dcron OR fcron'. @@ -186,9 +190,13 @@ name. The syntax is: `source=('filename::url')`. dependency of other packages. Provisions involving the '>' and '<' operators are invalid as only specific versions of a package may be provided. ++ +If the provision name appears to be a library (ends with .so), makepkg will +try to find the library in the built package and append the correct +version. Appending the version yourself disables auto detection. *replaces (array)*:: - An array of packages that this package should replace, and can be used + An array of packages this package should replace. This can be used to handle renamed/combined packages. For example, if the 'j2re' package is renamed to 'jre', this directive allows future upgrades to continue as expected even though the package has moved. Sysupgrade is currently @@ -248,7 +256,7 @@ name. The syntax is: `source=('filename::url')`. build() Function ---------------- -In addition to the above directives, the optional build() bash function usually +In addition to the above directives, the optional build() function usually comprises the remainder of the PKGBUILD. This is directly sourced and executed by makepkg, so anything that bash or the system has available is available for use here. The function is run in `bash -e` mode, meaning any command that exits @@ -256,19 +264,19 @@ with a non-zero status will cause the function to exit. Be sure any exotic commands used are covered by `makedepends`. All of the above variables such as `pkgname` and `pkgver` are available for use -in the build function. In addition, makepkg defines three variables for your -use during the build and install process. These three variables are as follows: +in the build function. In addition, makepkg defines the following three +variables for use during the build and install process: *startdir*:: - This contains the absolute path to the directory where the PKGBUILD was + This contains the absolute path to the directory where the PKGBUILD is located, which is usually the output of `$(pwd)` when makepkg is started. *srcdir*:: - This points to the directory where makepkg extracts or copies all source + This contains the directory where makepkg extracts, or copies, all source files. *pkgdir*:: - This points to the directory where makepkg bundles the installed package + This contains the directory where makepkg bundles the installed package (this directory will become the root directory of your built package). If you create any variables of your own in the build function, it is @@ -301,8 +309,8 @@ Each split package uses a corresponding packaging function with name `package_foo()`, where `foo` is the name of the split package. All options and directives for the split packages default to the global values -given within the PKGBUILD. However, some of these can be overridden within each -split package's packaging function. The following variables can be overridden: +given in the PKGBUILD. Nevertheless, the following ones can be overridden within +each split package's packaging function: `pkgver`, `pkgrel`, `pkgdesc`, `arch`, `license`, `groups`, `depends`, `optdepends`, `provides`, `conflicts`, `replaces`, `backup`, `options`, `install` and `changelog`. @@ -363,7 +371,7 @@ makepkg supports building development versions of packages without having to manually update the pkgver in the PKGBUILD. This was formerly done using the separate utility 'versionpkg'. In order to utilize this functionality, your PKGBUILD must use correct variable names depending on the SCM being fetched -from. +from (e.g., 'makepkg-git', 'mplayer-svn'). *CVS*:: The generated pkgver will be the date the package is built. diff --git a/doc/index.txt b/doc/index.txt index c04ca8a9..4cc83132 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -41,7 +41,9 @@ configuration files dealing with pacman. * linkman:makepkg[8] * linkman:makepkg.conf[5] * linkman:pacman[8] +* linkman:pacman-key[8] * linkman:pacman.conf[5] +* linkman:pkgdelta[8] * linkman:repo-add[8] * linkman:vercmp[8] diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt index 57d6f6eb..e61f7ab3 100644 --- a/doc/makepkg.8.txt +++ b/doc/makepkg.8.txt @@ -11,24 +11,24 @@ makepkg - package build utility Synopsis -------- -makepkg [options] +'makepkg' [options] Description ----------- -makepkg is a script to automate the building of packages. The requirements for +'makepkg' is a script to automate the building of packages. The requirements for using the script are a build-capable \*nix platform and a custom build script for each package you wish to build (known as a PKGBUILD). See linkman:PKGBUILD[5] for details on creating your own build scripts. The advantage to a script-based build is that the work is only done once. Once -you have the build script for a package, makepkg will do the rest: download and +you have the build script for a package, 'makepkg' will do the rest: download and validate source files, check dependencies, configure the build-time settings, build the package, install the package into a temporary root, make customizations, generate meta-info, and package the whole thing up for pacman to use. -NOTE: makepkg uses your current locale by default and does not unset it when +NOTE: 'makepkg' uses your current locale by default and does not unset it when building packages. If you wish to share your build output with others when seeking help or for other purposes, you may wish to run "`LC_ALL=C makepkg`" so your logs and output are not localized. @@ -161,6 +161,18 @@ Options *\--nocheck*:: Do not run the check() function in the PKGBUILD or handle the checkdepends. +*\--sign*:: + Sign the resulting package with gpg, overriding the setting in + linkman:makepkg.conf[5]. + +*\--nosign*:: + Do not create a signature for the built package. + +*\--key* <key>:: + Specify a key to use when signing packages, overriding the GPGKEY setting + in linkman:makepkg.conf[5]. If not specified in either location, the + default key from the keyring will be used. + *\--noconfirm*:: (Passed to pacman) Prevent pacman from waiting for user input before proceeding with operations. diff --git a/doc/makepkg.conf.5.txt b/doc/makepkg.conf.5.txt index 30ddf0a6..3ce4759f 100644 --- a/doc/makepkg.conf.5.txt +++ b/doc/makepkg.conf.5.txt @@ -70,7 +70,7 @@ Options This is often used to set the number of jobs used, for example, `-j2`. Other flags that make accepts can also be passed. -**BUILDENV=(**fakeroot !distcc color !ccache check**)**:: +**BUILDENV=(**fakeroot !distcc color !ccache check !sign**)**:: This array contains options that affect the build environment, the defaults are shown here. All options should always be left in the array; to enable or disable an option simply remove or place an ``!'' at the front of the @@ -98,11 +98,22 @@ Options enabled or disabled for individual packages through the use of makepkg's `--check` and `--nocheck` options respectively. + *sign*;; + Generate a PGP signature file using GnuPG. This will execute `gpg + --detach-sign --use-agent` on the built package to generate a detached + signature file, using the GPG agent if it is available. The signature + file will be the entire filename of the package with a ``.sig'' + extension. + **DISTCC_HOSTS=**"host1 ...":: If using DistCC, this is used to specify a space-delimited list of hosts running in the DistCC cluster. In addition, you will want to modify your `MAKEFLAGS`. +**GPGKEY=**"":: + Specify a key to use for gpg signing instead of the default key in the + keyring. Can be overridden with makepkg's `--key` option. + **OPTIONS=(**strip !docs libtool emptydirs zipman**)**:: This array contains options that affect the default packaging. They are equivalent to options that can be placed in the PKGBUILD; the defaults are diff --git a/doc/pacman-key.8.txt b/doc/pacman-key.8.txt new file mode 100644 index 00000000..892f14df --- /dev/null +++ b/doc/pacman-key.8.txt @@ -0,0 +1,85 @@ +///// +vim:set ts=4 sw=4 syntax=asciidoc noet: +///// +pacman-key(8) +============= + + +Name +---- +pacman-key - manage pacman's list of trusted keys + + +Synopsis +-------- +'pacman-key' [options] <command> [arguments] + + +Description +----------- +'pacman-key' is a script used to manage pacman's keyring, which is the collection +of GnuPG keys used to check signed packages. It provides the ability to import +and export keys, fetch keys from keyservers and update the key trust database. + + +Options +------- +*\--config* <file>:: + Use an alternate config file instead of the +{sysconfdir}/pacman.conf+ + default. + +*\--gpgdir* <dir>:: + Set an alternate home directory for GnuPG. If unspecified, the value is + read from +{sysconfdir}/pacman.conf+. + + +Commands +------- +*-a, \--add* file ...:: + Add the key(s) contained in the specified file or files to pacman's + keyring. If a key already exists, update it. + +*\--adv* param ...:: + Use this option to issue particular GnuPG actions to pacman's keyring. This + option should be used with care as it can modify pacman's trust in + packages' signatures. + +*-d, \--del* keyid ...:: + Remove the key(s) identified by the specified keyid or keyids from pacman's + keyring. + +*-e, \--export* [keyid ...]:: + Export key(s) identified by the specified keyid to 'stdout'. If no keyid is + specified, all keys will be exported. + +*-f, \--finger* [keyid ...]:: + List a fingerprint for each specified keyid, or for all known keys if no + keyids are specified. + +*-h, \--help*:: + Output syntax and command line options. + +*-l, \--list*:: + Equivalent to --list-sigs from GnuPG. + +*-r, \--receive* keyserver keyid ...:: + Fetch the specified keyids from the specified key server URL. + +*\--reload*:: + Reloads the keys from the keyring package. + +*-t, \--trust* keyid:: + Set the trust level of the given key. + +*-u, \--updatedb*:: + Equivalent to \--check-trustdb in GnuPG. + +*-v, \--version*:: + Displays the program version. + + +See Also +-------- +linkman:pacman[8], linkman:pacman.conf[5] + +include::footer.txt[] diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index a4d41d0e..531c992a 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -149,6 +149,14 @@ Options Display debug messages. When reporting bugs, this option is recommended to be used. +*\--gpgdir* <dir>:: + Specify a directory of files used by GnuPG to verify package signatures (a + typical default is +{sysconfdir}/pacman.d/gnupg+). This directory should contain + two files: `pubring.gpg` and `trustdb.gpg`. `pubring.gpg` holds the public keys + of all packagers. `trustdb.gpg` contains a so-called trust database, which + specifies that the keys are authentic and trusted. *NOTE*: this is an absolute + path, the root path is not automatically prepended. + *\--logfile* <file>:: Specify an alternate log file. This is an absolute path, regardless of the installation root setting. diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index dcaeed7f..bdf0bc83 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -69,6 +69,15 @@ Options to the first cache directory with write access. *NOTE*: this is an absolute path, the root path is not automatically prepended. +*GPGDir =* path/to/gpg/dir:: + Overrides the default location of the directory containing configuration + files for GnuPG. A typical default is +{sysconfdir}/pacman.d/gnupg/+. + This directory should contain two files: `pubring.gpg` and `trustdb.gpg`. + `pubring.gpg` holds the public keys of all packagers. `trustdb.gpg` + contains a so-called trust database, which specifies that the keys are + authentic and trusted. + *NOTE*: this is an absolute path, the root path is not automatically + prepended. *LogFile =* '/path/to/file':: Overrides the default location of the pacman log file. A typical default @@ -151,9 +160,6 @@ Options Log action messages through syslog(). This will insert log entries into +{localstatedir}/log/messages+ or equivalent. -*ShowSize*:: - Display the size of individual packages for '\--sync' and '\--query' modes. - *UseDelta*:: Download delta files instead of complete packages if possible. Requires the xdelta3 program to be installed. @@ -168,6 +174,10 @@ Options Performs an approximate check for adequate available disk space before installing packages. +*VerbosePkgLists*:: + Displays name, version and size of target packages formatted + as a table for upgrade, sync and remove operations. + Repository Sections ------------------- Each repository section defines a section name and at least one location where diff --git a/doc/pkgdelta.8.txt b/doc/pkgdelta.8.txt new file mode 100644 index 00000000..2d99a87f --- /dev/null +++ b/doc/pkgdelta.8.txt @@ -0,0 +1,42 @@ +///// +vim:set ts=4 sw=4 syntax=asciidoc noet: +///// +pkgdelta(8) +========= + +Name +---- +pkgdelta - package delta generation utility + + +Synopsis +-------- +'pkgdelta' [-q] <package1> <package2> + + +Description +----------- +'pkgdelta' is used to create package delta files between two versions of the +same package. These files are essentially binary patches. linkman:pacman[8] can +download deltas instead of full package upgrades, and use them with the +previous versions of packages (in the package cache) to synthesize the upgraded +version of the packages. This likely reduces download sizes for upgrades +significantly. + +'pkgdelta' requires linkman:xdelta3[1] to do its job. + +Options +------- +*-q, \--quiet*:: + Be quiet. Do not output anything but warnings and errors. + +Examples +-------- + + $ pkgdelta libreoffice-3.3.2-1-x86_64.pkg.tar.xz libreoffice-3.3.2-2-x86_64.pkg.tar.xz + +See Also +-------- +linkman:pacman[8], linkman:xdelta3[1] + +include::footer.txt[] diff --git a/doc/repo-add.8.txt b/doc/repo-add.8.txt index 75f49ef5..01968827 100644 --- a/doc/repo-add.8.txt +++ b/doc/repo-add.8.txt @@ -10,26 +10,50 @@ repo-add - package database maintenance utility Synopsis -------- -repo-add [-d] [-f] [-q] <path-to-db> <package1> [<package2> ...] +'repo-add' [options] <path-to-db> <package|delta> [<package|delta> ...] -repo-remove [-q] <path-to-db> <packagename> [<packagename2> ...] +'repo-remove' [options] <path-to-db> <packagename|delta> [<packagename|delta> ...] Description ----------- -repo-add and repo-remove are two scripts to help build a package database for +'repo-add' and 'repo-remove' are two scripts to help build a package database for packages built with linkman:makepkg[8] and installed with linkman:pacman[8]. +They also handle package deltas produced by linkman:pkgdelta[8]. -repo-add will update a package database by reading a built package file. -Multiple packages to add can be specified on the command line. +'repo-add' will update a package database by reading a built package or package +delta file. Multiple packages and/or deltas to add can be specified on the +command line. -repo-remove will update a package database by removing the package name -specified on the command line. Multiple packages to remove can be specified -on the command line. +'repo-remove' will update a package database by removing the package name or +delta specified on the command line. Multiple packages and/or delta to remove +can be specified on the command line. -Options -------- +Common Options +-------------- +*-q, \--quiet*:: + Force this program to keep quiet and run silent except for warning and + error messages. + +*-s, \--sign*:: + Generate a PGP signature file using GnuPG. This will execute `gpg + --detach-sign --use-agent` on the generated database to generate a detached + signature file, using the GPG agent if it is available. The signature file + will be the entire filename of the database with a ``.sig'' extension. + +*-k, \--key* <key>:: + Specify a key to use when signing packages. Can also be specified using + the GPGKEY environmental variable. If not specified in either location, the + default key from the keyring will be used. + +*-v, \--verify*:: + Verify the PGP signature of the database before updating the database. + If the signature is invalid, an error is produced and the update does not + proceed. + +repo-add Options +---------------- *-d, \--delta*:: Automatically generate and add a delta file between the old entry and the new one, if the old package file is found next to the new one. @@ -39,12 +63,8 @@ Options specified packages. This is useful for creating databases listing all files in a given sync repository for tools that may use this information. -*-q, \--quiet*:: - Force this program to keep quiet and run silent except for warning and - error messages. - See Also -------- -linkman:makepkg[8], linkman:pacman[8] +linkman:makepkg[8], linkman:pacman[8], linkman:pkgdelta[8] include::footer.txt[] diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in index 81a11b1d..9a790fcf 100644 --- a/etc/makepkg.conf.in +++ b/etc/makepkg.conf.in @@ -8,9 +8,9 @@ # #-- The download utilities that makepkg should use to acquire sources # Format: 'protocol::agent' -DLAGENTS=('ftp::/usr/bin/wget -c --passive-ftp -t 3 --waitretry=3 -O %o %u' - 'http::/usr/bin/wget -c -t 3 --waitretry=3 -O %o %u' - 'https::/usr/bin/wget -c -t 3 --waitretry=3 --no-check-certificate -O %o %u' +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' 'rsync::/usr/bin/rsync -z %u %o' 'scp::/usr/bin/scp -C %u %o') @@ -39,7 +39,7 @@ CXXFLAGS="@CARCHFLAGS@-mtune=generic -O2 -pipe" # BUILD ENVIRONMENT ######################################################################### # -# Defaults: BUILDENV=(fakeroot !distcc color !ccache check) +# Defaults: BUILDENV=(fakeroot !distcc color !ccache check !sign) # A negated environment option will do the opposite of the comments below. # #-- fakeroot: Allow building packages as a non-root user @@ -47,8 +47,9 @@ CXXFLAGS="@CARCHFLAGS@-mtune=generic -O2 -pipe" #-- color: Colorize output messages #-- ccache: Use ccache to cache compilation #-- check: Run the check() function if present in the PKGBUILD +#-- sign: Generate PGP signature file # -BUILDENV=(fakeroot !distcc color !ccache check) +BUILDENV=(fakeroot !distcc color !ccache check !sign) # #-- If using DistCC, your MAKEFLAGS will also need modification. In addition, #-- specify a space-delimited list of hosts running in the DistCC cluster. @@ -100,6 +101,8 @@ PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod) #SRCPKGDEST=/home/srcpackages #-- Packager: name/email of the person or organization building packages #PACKAGER="John Doe <john@doe.com>" +#-- Specify a key to use for package signing +#GPGKEY="" ######################################################################### # EXTENSION DEFAULTS diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in index 1105db94..1d49fd71 100644 --- a/etc/pacman.conf.in +++ b/etc/pacman.conf.in @@ -13,6 +13,7 @@ #DBPath = @localstatedir@/lib/pacman/ #CacheDir = @localstatedir@/cache/pacman/pkg/ #LogFile = @localstatedir@/log/pacman.log +#GPGDir = @sysconfdir@/pacman.d/gnupg/ HoldPkg = pacman glibc # If upgrades are available for these packages they will be asked for first SyncFirst = pacman @@ -30,10 +31,10 @@ Architecture = auto # Misc options (all disabled by default) #UseSyslog -#ShowSize #UseDelta #TotalDownload #CheckSpace +#VerbosePkgLists # # REPOSITORIES diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index 1bda5714..b2b6d0d2 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -35,13 +35,14 @@ libalpm_la_SOURCES = \ diskspace.h diskspace.c \ dload.h dload.c \ error.c \ - graph.h \ + graph.h graph.c \ group.h group.c \ handle.h handle.c \ log.h log.c \ package.h package.c \ pkghash.h pkghash.c \ remove.h remove.c \ + signing.c signing.h \ sync.h sync.c \ trans.h trans.c \ util.h util.c \ @@ -52,7 +53,12 @@ libalpm_la_SOURCES += \ md5.h md5.c endif -libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO) +if HAVE_LIBGPGME +libalpm_la_SOURCES += \ + base64.h base64.c +endif + +libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO) @LIBCURL@ libalpm_la_LIBADD = $(LTLIBINTL) # vim:set ts=2 sw=2 noet: diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index ad6ef17e..7b394a5b 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -37,50 +37,44 @@ /* libalpm */ #include "add.h" +#include "alpm.h" #include "alpm_list.h" +#include "handle.h" #include "trans.h" #include "util.h" #include "log.h" #include "backup.h" #include "package.h" #include "db.h" -#include "conflict.h" -#include "deps.h" #include "remove.h" #include "handle.h" -/** Add a package to the transaction. - * @param pkg the package to add - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_add_pkg(pmpkg_t *pkg) +/** Add a package to the transaction. */ +int SYMEXPORT alpm_add_pkg(pmhandle_t *handle, pmpkg_t *pkg) { const char *pkgname, *pkgver; pmtrans_t *trans; - pmdb_t *db_local; pmpkg_t *local; - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(pkg != NULL, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle == pkg->handle, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - db_local = handle->db_local; + ASSERT(trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, + RET_ERR(handle, PM_ERR_TRANS_NOT_INITIALIZED, -1)); - pkgname = alpm_pkg_get_name(pkg); - pkgver = alpm_pkg_get_version(pkg); + pkgname = pkg->name; + pkgver = pkg->version; - _alpm_log(PM_LOG_DEBUG, "adding package '%s'\n", pkgname); + _alpm_log(handle, PM_LOG_DEBUG, "adding package '%s'\n", pkgname); if(_alpm_pkg_find(trans->add, pkgname)) { - RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); + RET_ERR(handle, PM_ERR_TRANS_DUP_TARGET, -1); } - local = _alpm_db_get_pkgfromcache(db_local, pkgname); + local = _alpm_db_get_pkgfromcache(handle->db_local, pkgname); if(local) { const char *localpkgname = alpm_pkg_get_name(local); const char *localpkgver = alpm_pkg_get_version(local); @@ -89,30 +83,30 @@ int SYMEXPORT alpm_add_pkg(pmpkg_t *pkg) if(cmp == 0) { if(trans->flags & PM_TRANS_FLAG_NEEDED) { /* with the NEEDED flag, packages up to date are not reinstalled */ - _alpm_log(PM_LOG_WARNING, _("%s-%s is up to date -- skipping\n"), + _alpm_log(handle, PM_LOG_WARNING, _("%s-%s is up to date -- skipping\n"), localpkgname, localpkgver); - return(0); + return 0; } else if(!(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY)) { - _alpm_log(PM_LOG_WARNING, _("%s-%s is up to date -- reinstalling\n"), + _alpm_log(handle, PM_LOG_WARNING, _("%s-%s is up to date -- reinstalling\n"), localpkgname, localpkgver); } } else if(cmp < 0) { /* local version is newer */ - _alpm_log(PM_LOG_WARNING, _("downgrading package %s (%s => %s)\n"), + _alpm_log(handle, PM_LOG_WARNING, _("downgrading package %s (%s => %s)\n"), localpkgname, localpkgver, pkgver); } } /* add the package to the transaction */ pkg->reason = PM_PKG_REASON_EXPLICIT; - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", + _alpm_log(handle, PM_LOG_DEBUG, "adding package %s-%s to the transaction add list\n", pkgname, pkgver); trans->add = alpm_list_add(trans->add, pkg); - return(0); + return 0; } -static int perform_extraction(struct archive *archive, +static int perform_extraction(pmhandle_t *handle, struct archive *archive, struct archive_entry *entry, const char *filename, const char *origname) { int ret; @@ -125,21 +119,20 @@ static int perform_extraction(struct archive *archive, ret = archive_read_extract(archive, entry, archive_flags); if(ret == ARCHIVE_WARN && archive_errno(archive) != ENOSPC) { /* operation succeeded but a "non-critical" error was encountered */ - _alpm_log(PM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), + _alpm_log(handle, PM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), origname, archive_error_string(archive)); } else if(ret != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not extract %s (%s)\n"), origname, archive_error_string(archive)); - alpm_logaction("error: could not extract %s (%s)\n", + alpm_logaction(handle, "error: could not extract %s (%s)\n", origname, archive_error_string(archive)); - return(1); + return 1; } - return(0); + return 0; } -static int extract_single_file(struct archive *archive, - struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg, - pmtrans_t *trans, pmdb_t *db) +static int extract_single_file(pmhandle_t *handle, struct archive *archive, + struct archive_entry *entry, pmpkg_t *newpkg, pmpkg_t *oldpkg) { const char *entryname; mode_t entrymode; @@ -157,19 +150,19 @@ static int extract_single_file(struct archive *archive, if(strcmp(entryname, ".INSTALL") == 0) { /* the install script goes inside the db */ snprintf(filename, PATH_MAX, "%s%s-%s/install", - _alpm_db_path(db), newpkg->name, newpkg->version); + _alpm_db_path(handle->db_local), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(strcmp(entryname, ".CHANGELOG") == 0) { /* the changelog goes inside the db */ snprintf(filename, PATH_MAX, "%s%s-%s/changelog", - _alpm_db_path(db), newpkg->name, newpkg->version); + _alpm_db_path(handle->db_local), newpkg->name, newpkg->version); archive_entry_set_perm(entry, 0644); } else if(*entryname == '.') { /* for now, ignore all files starting with '.' that haven't * already been handled (for future possibilities) */ - _alpm_log(PM_LOG_DEBUG, "skipping extraction of '%s'\n", entryname); + _alpm_log(handle, PM_LOG_DEBUG, "skipping extraction of '%s'\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } else { /* build the new entryname relative to handle->root */ snprintf(filename, PATH_MAX, "%s%s", handle->root, entryname); @@ -177,12 +170,12 @@ static int extract_single_file(struct archive *archive, /* if a file is in NoExtract then we never extract it */ if(alpm_list_find_str(handle->noextract, entryname)) { - _alpm_log(PM_LOG_DEBUG, "%s is in NoExtract, skipping extraction\n", + _alpm_log(handle, PM_LOG_DEBUG, "%s is in NoExtract, skipping extraction\n", entryname); - alpm_logaction("note: %s is in NoExtract, skipping extraction\n", + alpm_logaction(handle, "note: %s is in NoExtract, skipping extraction\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } /* Check for file existence. This is one of the more crucial parts @@ -216,42 +209,42 @@ static int extract_single_file(struct archive *archive, if(lsbuf.st_mode != entrymode) { /* if filesystem perms are different than pkg perms, warn user */ mode_t mask = 07777; - _alpm_log(PM_LOG_WARNING, _("directory permissions differ on %s\n" + _alpm_log(handle, PM_LOG_WARNING, _("directory permissions differ on %s\n" "filesystem: %o package: %o\n"), entryname, lsbuf.st_mode & mask, entrymode & mask); - alpm_logaction("warning: directory permissions differ on %s\n" + alpm_logaction(handle, "warning: directory permissions differ on %s\n" "filesystem: %o package: %o\n", entryname, lsbuf.st_mode & mask, entrymode & mask); } - _alpm_log(PM_LOG_DEBUG, "extract: skipping dir extraction of %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "extract: skipping dir extraction of %s\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } else { /* case 10/11: trying to overwrite dir with file/symlink, don't allow it */ - _alpm_log(PM_LOG_ERROR, _("extract: not overwriting dir with file %s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("extract: not overwriting dir with file %s\n"), entryname); archive_read_data_skip(archive); - return(1); + return 1; } } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(entrymode)) { /* case 9: existing symlink, dir in package */ if(S_ISDIR(sbuf.st_mode)) { /* the symlink on FS is to a directory, so we'll use it */ - _alpm_log(PM_LOG_DEBUG, "extract: skipping symlink overwrite of %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "extract: skipping symlink overwrite of %s\n", entryname); archive_read_data_skip(archive); - return(0); + return 0; } else { /* this is BAD. symlink was not to a directory */ - _alpm_log(PM_LOG_ERROR, _("extract: symlink %s does not point to dir\n"), + _alpm_log(handle, PM_LOG_ERROR, _("extract: symlink %s does not point to dir\n"), entryname); archive_read_data_skip(archive); - return(1); + return 1; } } else if(S_ISREG(lsbuf.st_mode) && S_ISDIR(entrymode)) { /* case 6: trying to overwrite file with dir */ - _alpm_log(PM_LOG_DEBUG, "extract: overwriting file with dir %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "extract: overwriting file with dir %s\n", entryname); } else if(S_ISREG(entrymode)) { /* case 4,7: */ @@ -275,7 +268,7 @@ static int extract_single_file(struct archive *archive, /* if we force hash_orig to be non-NULL retroactive backup works */ if(needbackup && !hash_orig) { - STRDUP(hash_orig, "", RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(hash_orig, "", RET_ERR(handle, PM_ERR_MEMORY, -1)); } } } @@ -285,7 +278,7 @@ static int extract_single_file(struct archive *archive, /* we need access to the original entryname later after calls to * archive_entry_set_pathname(), so we need to dupe it and free() later */ - STRDUP(entryname_orig, entryname, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(entryname_orig, entryname, RET_ERR(handle, PM_ERR_MEMORY, -1)); if(needbackup) { char checkfile[PATH_MAX]; @@ -294,12 +287,12 @@ static int extract_single_file(struct archive *archive, snprintf(checkfile, PATH_MAX, "%s.paccheck", filename); - ret = perform_extraction(archive, entry, checkfile, entryname_orig); + ret = perform_extraction(handle, archive, entry, checkfile, entryname_orig); if(ret == 1) { /* error */ FREE(hash_orig); FREE(entryname_orig); - return(1); + return 1; } hash_local = alpm_compute_md5sum(filename); @@ -317,7 +310,7 @@ static int extract_single_file(struct archive *archive, char *backup = NULL; /* length is tab char, null byte and MD5 (32 char) */ size_t backup_len = strlen(oldbackup) + 34; - MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1)); + MALLOC(backup, backup_len, RET_ERR(handle, PM_ERR_MEMORY, -1)); sprintf(backup, "%s\t%s", oldbackup, hash_pkg); backup[backup_len-1] = '\0'; @@ -325,10 +318,10 @@ static int extract_single_file(struct archive *archive, backups->data = backup; } - _alpm_log(PM_LOG_DEBUG, "checking hashes for %s\n", entryname_orig); - _alpm_log(PM_LOG_DEBUG, "current: %s\n", hash_local); - _alpm_log(PM_LOG_DEBUG, "new: %s\n", hash_pkg); - _alpm_log(PM_LOG_DEBUG, "original: %s\n", hash_orig); + _alpm_log(handle, PM_LOG_DEBUG, "checking hashes for %s\n", entryname_orig); + _alpm_log(handle, PM_LOG_DEBUG, "current: %s\n", hash_local); + _alpm_log(handle, PM_LOG_DEBUG, "new: %s\n", hash_pkg); + _alpm_log(handle, PM_LOG_DEBUG, "original: %s\n", hash_orig); if(!oldpkg) { if(strcmp(hash_local, hash_pkg) != 0) { @@ -339,22 +332,22 @@ static int extract_single_file(struct archive *archive, /* move the existing file to the "pacorig" */ if(rename(filename, newpath)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), filename, newpath, strerror(errno)); - alpm_logaction("error: could not rename %s to %s (%s)\n", + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", filename, newpath, strerror(errno)); errors++; } else { /* rename the file we extracted to the real name */ if(rename(checkfile, filename)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), checkfile, filename, strerror(errno)); - alpm_logaction("error: could not rename %s to %s (%s)\n", + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", checkfile, filename, strerror(errno)); errors++; } else { - _alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath); - alpm_logaction("warning: %s saved as %s\n", filename, newpath); + _alpm_log(handle, PM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath); + alpm_logaction(handle, "warning: %s saved as %s\n", filename, newpath); } } } else { @@ -367,48 +360,48 @@ static int extract_single_file(struct archive *archive, if(strcmp(hash_orig, hash_local) == 0) { /* installed file has NOT been changed by user */ if(strcmp(hash_orig, hash_pkg) != 0) { - _alpm_log(PM_LOG_DEBUG, "action: installing new file: %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "action: installing new file: %s\n", entryname_orig); if(rename(checkfile, filename)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), checkfile, filename, strerror(errno)); - alpm_logaction("error: could not rename %s to %s (%s)\n", + alpm_logaction(handle, "error: could not rename %s to %s (%s)\n", checkfile, filename, strerror(errno)); errors++; } } else { /* there's no sense in installing the same file twice, install * ONLY is the original and package hashes differ */ - _alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); + _alpm_log(handle, PM_LOG_DEBUG, "action: leaving existing file in place\n"); unlink(checkfile); } } else if(strcmp(hash_orig, hash_pkg) == 0) { /* originally installed file and new file are the same - this * implies the case above failed - i.e. the file was changed by a * user */ - _alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); + _alpm_log(handle, PM_LOG_DEBUG, "action: leaving existing file in place\n"); unlink(checkfile); } else if(strcmp(hash_local, hash_pkg) == 0) { /* this would be magical. The above two cases failed, but the * user changes just so happened to make the new file exactly the * same as the one in the package... skip it */ - _alpm_log(PM_LOG_DEBUG, "action: leaving existing file in place\n"); + _alpm_log(handle, PM_LOG_DEBUG, "action: leaving existing file in place\n"); unlink(checkfile); } else { char newpath[PATH_MAX]; - _alpm_log(PM_LOG_DEBUG, "action: keeping current file and installing" + _alpm_log(handle, PM_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(PM_LOG_ERROR, _("could not install %s as %s (%s)\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not install %s as %s (%s)\n"), filename, newpath, strerror(errno)); - alpm_logaction("error: could not install %s as %s (%s)\n", + alpm_logaction(handle, "error: could not install %s as %s (%s)\n", filename, newpath, strerror(errno)); } else { - _alpm_log(PM_LOG_WARNING, _("%s installed as %s\n"), + _alpm_log(handle, PM_LOG_WARNING, _("%s installed as %s\n"), filename, newpath); - alpm_logaction("warning: %s installed as %s\n", + alpm_logaction(handle, "warning: %s installed as %s\n", filename, newpath); } } @@ -423,26 +416,26 @@ static int extract_single_file(struct archive *archive, /* we didn't need a backup */ if(notouch) { /* change the path to a .pacnew extension */ - _alpm_log(PM_LOG_DEBUG, "%s is in NoUpgrade -- skipping\n", filename); - _alpm_log(PM_LOG_WARNING, _("extracting %s as %s.pacnew\n"), filename, filename); - alpm_logaction("warning: extracting %s as %s.pacnew\n", filename, filename); + _alpm_log(handle, PM_LOG_DEBUG, "%s is in NoUpgrade -- skipping\n", filename); + _alpm_log(handle, PM_LOG_WARNING, _("extracting %s as %s.pacnew\n"), filename, filename); + alpm_logaction(handle, "warning: extracting %s as %s.pacnew\n", filename, filename); strncat(filename, ".pacnew", PATH_MAX - strlen(filename)); } else { - _alpm_log(PM_LOG_DEBUG, "extracting %s\n", filename); + _alpm_log(handle, PM_LOG_DEBUG, "extracting %s\n", filename); } - if(trans->flags & PM_TRANS_FLAG_FORCE) { + if(handle->trans->flags & PM_TRANS_FLAG_FORCE) { /* if FORCE was used, unlink() each file (whether it's there * or not) before extracting. This prevents the old "Text file busy" * error that crops up if forcing a glibc or pacman upgrade. */ unlink(filename); } - ret = perform_extraction(archive, entry, filename, entryname_orig); + ret = perform_extraction(handle, archive, entry, filename, entryname_orig); if(ret == 1) { /* error */ FREE(entryname_orig); - return(1); + return 1; } /* calculate an hash if this is in newpkg's backup */ @@ -456,10 +449,10 @@ static int extract_single_file(struct archive *archive, if(!oldbackup || strcmp(oldbackup, entryname_orig) != 0) { continue; } - _alpm_log(PM_LOG_DEBUG, "appending backup entry for %s\n", filename); + _alpm_log(handle, PM_LOG_DEBUG, "appending backup entry for %s\n", filename); hash = alpm_compute_md5sum(filename); - MALLOC(backup, backup_len, RET_ERR(PM_ERR_MEMORY, -1)); + MALLOC(backup, backup_len, RET_ERR(handle, PM_ERR_MEMORY, -1)); sprintf(backup, "%s\t%s", oldbackup, hash); backup[backup_len-1] = '\0'; @@ -469,20 +462,18 @@ static int extract_single_file(struct archive *archive, } } FREE(entryname_orig); - return(errors); + return errors; } -static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, - size_t pkg_count, pmtrans_t *trans, pmdb_t *db) +static int commit_single_pkg(pmhandle_t *handle, pmpkg_t *newpkg, + size_t pkg_current, size_t pkg_count) { int i, ret = 0, errors = 0; - char scriptlet[PATH_MAX+1]; + char scriptlet[PATH_MAX]; int is_upgrade = 0; pmpkg_t *oldpkg = NULL; - - ALPM_LOG_FUNC; - - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + pmdb_t *db = handle->db_local; + pmtrans_t *trans = handle->trans; snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", _alpm_db_path(db), alpm_pkg_get_name(newpkg), @@ -500,7 +491,7 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, _alpm_local_db_read(oldpkg->origin_data.db, oldpkg, INFRQ_ALL); EVENT(trans, PM_TRANS_EVT_UPGRADE_START, newpkg, oldpkg); - _alpm_log(PM_LOG_DEBUG, "upgrading package %s-%s\n", + _alpm_log(handle, PM_LOG_DEBUG, "upgrading package %s-%s\n", newpkg->name, newpkg->version); /* copy over the install reason */ @@ -508,20 +499,20 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, /* pre_upgrade scriptlet */ if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, newpkg->origin_data.file, - "pre_upgrade", newpkg->version, oldpkg->version, trans); + _alpm_runscriptlet(handle, newpkg->origin_data.file, + "pre_upgrade", newpkg->version, oldpkg->version); } } else { is_upgrade = 0; EVENT(trans, PM_TRANS_EVT_ADD_START, newpkg, NULL); - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s\n", + _alpm_log(handle, PM_LOG_DEBUG, "adding package %s-%s\n", newpkg->name, newpkg->version); /* pre_install scriptlet */ if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, newpkg->origin_data.file, - "pre_install", newpkg->version, NULL, trans); + _alpm_runscriptlet(handle, newpkg->origin_data.file, + "pre_install", newpkg->version, NULL); } } @@ -534,8 +525,8 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, if(oldpkg) { /* set up fake remove transaction */ - if(_alpm_upgraderemove_package(oldpkg, newpkg, trans) == -1) { - pm_errno = PM_ERR_TRANS_ABORT; + if(_alpm_upgraderemove_package(handle, oldpkg, newpkg) == -1) { + handle->pm_errno = PM_ERR_TRANS_ABORT; ret = -1; goto cleanup; } @@ -544,9 +535,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, /* prepare directory for database entries so permission are correct after changelog/install script installation (FS#12263) */ if(_alpm_local_db_prepare(db, newpkg)) { - alpm_logaction("error: could not create database entry %s-%s\n", + alpm_logaction(handle, "error: could not create database entry %s-%s\n", alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); - pm_errno = PM_ERR_DB_WRITE; + handle->pm_errno = PM_ERR_DB_WRITE; ret = -1; goto cleanup; } @@ -557,10 +548,10 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, char cwd[PATH_MAX] = ""; int restore_cwd = 0; - _alpm_log(PM_LOG_DEBUG, "extracting files\n"); + _alpm_log(handle, PM_LOG_DEBUG, "extracting files\n"); - if ((archive = archive_read_new()) == NULL) { - pm_errno = PM_ERR_LIBARCHIVE; + if((archive = archive_read_new()) == NULL) { + handle->pm_errno = PM_ERR_LIBARCHIVE; ret = -1; goto cleanup; } @@ -568,24 +559,25 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - _alpm_log(PM_LOG_DEBUG, "archive: %s\n", newpkg->origin_data.file); + _alpm_log(handle, PM_LOG_DEBUG, "archive: %s\n", newpkg->origin_data.file); if(archive_read_open_filename(archive, newpkg->origin_data.file, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - pm_errno = PM_ERR_PKG_OPEN; + handle->pm_errno = PM_ERR_PKG_OPEN; ret = -1; goto cleanup; } /* save the cwd so we can restore it later */ if(getcwd(cwd, PATH_MAX) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); + _alpm_log(handle, PM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* libarchive requires this for extracting hard links */ if(chdir(handle->root) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), handle->root, strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + handle->root, strerror(errno)); ret = -1; goto cleanup; } @@ -608,7 +600,7 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, * (missing metadata sizes) */ int64_t pos = archive_position_compressed(archive); percent = (pos * 100) / newpkg->size; - _alpm_log(PM_LOG_DEBUG, "decompression progress: " + _alpm_log(handle, PM_LOG_DEBUG, "decompression progress: " "%d%% (%"PRId64" / %jd)\n", percent, pos, (intmax_t)newpkg->size); if(percent >= 100) { @@ -629,27 +621,26 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, } /* extract the next file from the archive */ - errors += extract_single_file(archive, entry, newpkg, oldpkg, - trans, db); + errors += extract_single_file(handle, archive, entry, newpkg, oldpkg); } archive_read_finish(archive); /* restore the old cwd if we have it */ if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); } if(errors) { ret = -1; if(is_upgrade) { - _alpm_log(PM_LOG_ERROR, _("problem occurred while upgrading %s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("problem occurred while upgrading %s\n"), newpkg->name); - alpm_logaction("error: problem occurred while upgrading %s\n", + alpm_logaction(handle, "error: problem occurred while upgrading %s\n", newpkg->name); } else { - _alpm_log(PM_LOG_ERROR, _("problem occurred while installing %s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("problem occurred while installing %s\n"), newpkg->name); - alpm_logaction("error: problem occurred while installing %s\n", + alpm_logaction(handle, "error: problem occurred while installing %s\n", newpkg->name); } } @@ -658,21 +649,21 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, /* make an install date (in UTC) */ newpkg->installdate = time(NULL); - _alpm_log(PM_LOG_DEBUG, "updating database\n"); - _alpm_log(PM_LOG_DEBUG, "adding database entry '%s'\n", newpkg->name); + _alpm_log(handle, PM_LOG_DEBUG, "updating database\n"); + _alpm_log(handle, PM_LOG_DEBUG, "adding database entry '%s'\n", newpkg->name); if(_alpm_local_db_write(db, newpkg, INFRQ_ALL)) { - _alpm_log(PM_LOG_ERROR, _("could not update database entry %s-%s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not update database entry %s-%s\n"), alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); - alpm_logaction("error: could not update database entry %s-%s\n", + alpm_logaction(handle, "error: could not update database entry %s-%s\n", alpm_pkg_get_name(newpkg), alpm_pkg_get_version(newpkg)); - pm_errno = PM_ERR_DB_WRITE; + handle->pm_errno = PM_ERR_DB_WRITE; ret = -1; goto cleanup; } if(_alpm_db_add_pkgincache(db, newpkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not add entry '%s' in cache\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not add entry '%s' in cache\n"), alpm_pkg_get_name(newpkg)); } @@ -688,12 +679,12 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { if(is_upgrade) { - _alpm_runscriptlet(handle->root, scriptlet, "post_upgrade", + _alpm_runscriptlet(handle, scriptlet, "post_upgrade", alpm_pkg_get_version(newpkg), - oldpkg ? alpm_pkg_get_version(oldpkg) : NULL, trans); + oldpkg ? alpm_pkg_get_version(oldpkg) : NULL); } else { - _alpm_runscriptlet(handle->root, scriptlet, "post_install", - alpm_pkg_get_version(newpkg), NULL, trans); + _alpm_runscriptlet(handle, scriptlet, "post_install", + alpm_pkg_get_version(newpkg), NULL); } } @@ -705,22 +696,18 @@ static int commit_single_pkg(pmpkg_t *newpkg, size_t pkg_current, cleanup: _alpm_pkg_free(oldpkg); - return(ret); + return ret; } -int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) +int _alpm_upgrade_packages(pmhandle_t *handle) { size_t pkg_count, pkg_current; int skip_ldconfig = 0, ret = 0; alpm_list_t *targ; - - ALPM_LOG_FUNC; - - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); + pmtrans_t *trans = handle->trans; if(trans->add == NULL) { - return(0); + return 0; } pkg_count = alpm_list_count(trans->add); @@ -728,15 +715,16 @@ int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) /* loop through our package list adding/upgrading one at a time */ for(targ = trans->add; targ; targ = targ->next) { + pmpkg_t *newpkg = targ->data; + if(handle->trans->state == STATE_INTERRUPTED) { - return(ret); + return ret; } - pmpkg_t *newpkg = (pmpkg_t *)targ->data; - if(commit_single_pkg(newpkg, pkg_current, pkg_count, trans, db)) { + if(commit_single_pkg(handle, newpkg, pkg_current, pkg_count)) { /* something screwed up on the commit, abort the trans */ trans->state = STATE_INTERRUPTED; - pm_errno = PM_ERR_TRANS_ABORT; + handle->pm_errno = PM_ERR_TRANS_ABORT; /* running ldconfig at this point could possibly screw system */ skip_ldconfig = 1; ret = -1; @@ -747,10 +735,10 @@ int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) if(!skip_ldconfig) { /* run ldconfig if it exists */ - _alpm_ldconfig(handle->root); + _alpm_ldconfig(handle); } - return(ret); + return ret; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h index afc7be26..1baab8d4 100644 --- a/lib/libalpm/add.h +++ b/lib/libalpm/add.h @@ -24,7 +24,7 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db); +int _alpm_upgrade_packages(pmhandle_t *handle); #endif /* _ALPM_ADD_H */ diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index a60a4bb6..9b9719d1 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -23,20 +23,17 @@ #include "config.h" -/* connection caching setup */ -#ifdef HAVE_LIBFETCH -#include <fetch.h> +#ifdef HAVE_LIBCURL +#include <curl/curl.h> #endif /* libalpm */ #include "alpm.h" #include "alpm_list.h" #include "handle.h" +#include "log.h" #include "util.h" -/* Globals */ -enum _pmerrno_t pm_errno SYMEXPORT; - /** \addtogroup alpm_interface Interface Functions * @brief Functions to initialize and release libalpm * @{ @@ -44,64 +41,89 @@ enum _pmerrno_t pm_errno SYMEXPORT; /** Initializes the library. This must be called before any other * functions are called. - * @return 0 on success, -1 on error (pm_errno is set accordingly) + * @param root the root path for all filesystem operations + * @param dbpath the absolute path to the libalpm database + * @param err an optional variable to hold any error return codes + * @return a context handle on success, NULL on error, err will be set if provided */ -int SYMEXPORT alpm_initialize(void) +pmhandle_t SYMEXPORT *alpm_initialize(const char *root, const char *dbpath, + enum _pmerrno_t *err) { - ASSERT(handle == NULL, RET_ERR(PM_ERR_HANDLE_NOT_NULL, -1)); - - handle = _alpm_handle_new(); - if(handle == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); + enum _pmerrno_t myerr; + const char *lf = "db.lck"; + size_t lockfilelen; + pmhandle_t *myhandle = _alpm_handle_new(); + + if(myhandle == NULL) { + myerr = PM_ERR_MEMORY; + goto cleanup; + } + if((myerr = _alpm_set_directory_option(root, &(myhandle->root), 1))) { + goto cleanup; } - if(_alpm_db_register_local() == NULL) { - /* error code should be set */ - _alpm_handle_free(handle); - handle = NULL; - return(-1); + if((myerr = _alpm_set_directory_option(dbpath, &(myhandle->dbpath), 1))) { + goto cleanup; + } + + lockfilelen = strlen(myhandle->dbpath) + strlen(lf) + 1; + myhandle->lockfile = calloc(lockfilelen, sizeof(char)); + snprintf(myhandle->lockfile, lockfilelen, "%s%s", myhandle->dbpath, lf); + + if(_alpm_db_register_local(myhandle) == NULL) { + myerr = PM_ERR_DB_CREATE; + goto cleanup; } #ifdef ENABLE_NLS bindtextdomain("libalpm", LOCALEDIR); #endif -#ifdef HAVE_LIBFETCH - fetchConnectionCacheInit(5, 1); +#ifdef HAVE_LIBCURL + curl_global_init(CURL_GLOBAL_SSL); + myhandle->curl = curl_easy_init(); #endif - return(0); + return myhandle; + +cleanup: + _alpm_handle_free(myhandle); + if(err && myerr) { + *err = myerr; + } + return NULL; } /** Release the library. This should be the last alpm call you make. - * @return 0 on success, -1 on error (pm_errno is set accordingly) + * After this returns, handle should be considered invalid and cannot be reused + * in any way. + * @param handle the context handle + * @return 0 on success, -1 on error */ -int SYMEXPORT alpm_release(void) +int SYMEXPORT alpm_release(pmhandle_t *myhandle) { + int ret = 0; pmdb_t *db; - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(myhandle, return -1); /* close local database */ - db = handle->db_local; + db = myhandle->db_local; if(db) { db->ops->unregister(db); - handle->db_local = NULL; + myhandle->db_local = NULL; } - if(alpm_db_unregister_all() == -1) { - return(-1); + if(alpm_db_unregister_all(myhandle) == -1) { + ret = -1; } - _alpm_handle_free(handle); - handle = NULL; + _alpm_handle_free(myhandle); -#ifdef HAVE_LIBFETCH - fetchConnectionCacheClose(); +#ifdef HAVE_LIBCURL + curl_global_cleanup(); #endif - return(0); + return ret; } /** @} */ @@ -112,7 +134,7 @@ int SYMEXPORT alpm_release(void) /* Get the version of library */ const char SYMEXPORT *alpm_version(void) { - return(LIB_VERSION); + return LIB_VERSION; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index cb643d29..845bd478 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -45,9 +45,36 @@ extern "C" { */ /* + * Enumerations + * These ones are used in multiple contexts, so are forward-declared. + */ + +/** + * Install reasons + * Why the package was installed. + */ +typedef enum _pmpkgreason_t { + /** Explicitly requested by the user. */ + PM_PKG_REASON_EXPLICIT = 0, + /** Installed as a dependency for another package. */ + PM_PKG_REASON_DEPEND = 1 +} pmpkgreason_t; + +/** + * GPG signature verification options + */ +typedef enum _pgp_verify_t { + PM_PGP_VERIFY_UNKNOWN, + PM_PGP_VERIFY_NEVER, + PM_PGP_VERIFY_OPTIONAL, + PM_PGP_VERIFY_ALWAYS +} pgp_verify_t; + +/* * Structures */ +typedef struct __pmhandle_t pmhandle_t; typedef struct __pmdb_t pmdb_t; typedef struct __pmpkg_t pmpkg_t; typedef struct __pmdelta_t pmdelta_t; @@ -59,18 +86,12 @@ typedef struct __pmconflict_t pmconflict_t; typedef struct __pmfileconflict_t pmfileconflict_t; /* - * Library - */ - -int alpm_initialize(void); -int alpm_release(void); -const char *alpm_version(void); - -/* * Logging facilities */ -/* Levels */ +/** + * Logging Levels + */ typedef enum _pmloglevel_t { PM_LOG_ERROR = 1, PM_LOG_WARNING = (1 << 1), @@ -79,15 +100,22 @@ typedef enum _pmloglevel_t { } pmloglevel_t; typedef void (*alpm_cb_log)(pmloglevel_t, const char *, va_list); -int alpm_logaction(const char *fmt, ...); +int alpm_logaction(pmhandle_t *handle, const char *fmt, ...); /* * Downloading */ +/** Type of download progress callbacks. + * @param filename the name of the file being downloaded + * @param xfered the number of transferred bytes + * @param total the total number of bytes to transfer + */ typedef void (*alpm_cb_download)(const char *filename, off_t xfered, off_t total); + typedef void (*alpm_cb_totaldl)(off_t total); + /** A callback for downloading files * @param url the URL of the file to be downloaded * @param localpath the directory to which the file should be downloaded @@ -99,111 +127,131 @@ typedef int (*alpm_cb_fetch)(const char *url, const char *localpath, int force); /** Fetch a remote pkg. + * @param handle the context handle * @param url URL of the package to download * @return the downloaded filepath on success, NULL on error */ -char *alpm_fetch_pkgurl(const char *url); +char *alpm_fetch_pkgurl(pmhandle_t *handle, const char *url); /** @addtogroup alpm_api_options Options * Libalpm option getters and setters * @{ */ -/** @name The logging callback. */ -/* @{ */ -alpm_cb_log alpm_option_get_logcb(void); -void alpm_option_set_logcb(alpm_cb_log cb); -/* @} */ +/** Returns the callback used for logging. */ +alpm_cb_log alpm_option_get_logcb(pmhandle_t *handle); +/** Sets the callback used for logging. */ +int alpm_option_set_logcb(pmhandle_t *handle, alpm_cb_log cb); -/** Get/set the download progress callback. */ -alpm_cb_download alpm_option_get_dlcb(void); -void alpm_option_set_dlcb(alpm_cb_download cb); +/** Returns the callback used to report download progress. */ +alpm_cb_download alpm_option_get_dlcb(pmhandle_t *handle); +/** Sets the callback used to report download progress. */ +int alpm_option_set_dlcb(pmhandle_t *handle, alpm_cb_download cb); -/** Get/set the downloader callback. */ -alpm_cb_fetch alpm_option_get_fetchcb(void); -void alpm_option_set_fetchcb(alpm_cb_fetch cb); +/** Returns the downloading callback. */ +alpm_cb_fetch alpm_option_get_fetchcb(pmhandle_t *handle); +/** Sets the downloading callback. */ +int alpm_option_set_fetchcb(pmhandle_t *handle, alpm_cb_fetch cb); -/** Get/set the callback used when download size is known. */ -alpm_cb_totaldl alpm_option_get_totaldlcb(void); -void alpm_option_set_totaldlcb(alpm_cb_totaldl cb); +/** Returns the callback used to report total download size. */ +alpm_cb_totaldl alpm_option_get_totaldlcb(pmhandle_t *handle); +/** Sets the callback used to report total download size. */ +int alpm_option_set_totaldlcb(pmhandle_t *handle, alpm_cb_totaldl cb); -/** Get/set the root of the destination filesystem. */ -const char *alpm_option_get_root(void); -int alpm_option_set_root(const char *root); +/** Returns the root of the destination filesystem. Read-only. */ +const char *alpm_option_get_root(pmhandle_t *handle); -/** Get/set the path to the database directory. */ -const char *alpm_option_get_dbpath(void); -int alpm_option_set_dbpath(const char *dbpath); +/** Returns the path to the database directory. Read-only. */ +const char *alpm_option_get_dbpath(pmhandle_t *handle); -/** Get/set the list of package cache directories. */ -alpm_list_t *alpm_option_get_cachedirs(void); -void alpm_option_set_cachedirs(alpm_list_t *cachedirs); +/** Get the name of the database lock file. Read-only. */ +const char *alpm_option_get_lockfile(pmhandle_t *handle); -/** Add a single directory to the package cache paths. */ -int alpm_option_add_cachedir(const char *cachedir); +/** @name Accessors to the list of package cache directories. + * @{ + */ +alpm_list_t *alpm_option_get_cachedirs(pmhandle_t *handle); +int alpm_option_set_cachedirs(pmhandle_t *handle, alpm_list_t *cachedirs); +int alpm_option_add_cachedir(pmhandle_t *handle, const char *cachedir); +int alpm_option_remove_cachedir(pmhandle_t *handle, const char *cachedir); +/** @} */ -/** Remove a single directory from the package cache paths. */ -int alpm_option_remove_cachedir(const char *cachedir); +/** Returns the logfile name. */ +const char *alpm_option_get_logfile(pmhandle_t *handle); +/** Sets the logfile name. */ +int alpm_option_set_logfile(pmhandle_t *handle, const char *logfile); -/** Get/set the logfile name. */ -const char *alpm_option_get_logfile(void); -int alpm_option_set_logfile(const char *logfile); +/** Returns the signature directory path. */ +const char *alpm_option_get_signaturedir(pmhandle_t *handle); +/** Sets the signature directory path. */ +int alpm_option_set_signaturedir(pmhandle_t *handle, const char *signaturedir); -/** Get the name of the database lock file. - * - * This properly is read-only, and determined from - * the database path. - * - * @sa alpm_option_set_dbpath(const char*) - */ -const char *alpm_option_get_lockfile(void); +/** Returns whether to use syslog (0 is FALSE, TRUE otherwise). */ +int alpm_option_get_usesyslog(pmhandle_t *handle); +/** Sets whether to use syslog (0 is FALSE, TRUE otherwise). */ +int alpm_option_set_usesyslog(pmhandle_t *handle, int usesyslog); -/** Get/set whether to use syslog (0 is FALSE, TRUE otherwise). */ -int alpm_option_get_usesyslog(void); -void alpm_option_set_usesyslog(int usesyslog); +/** @name Accessors to the list of no-upgrade files. + * These functions modify the list of files which should + * not be updated by package installation. + * @{ + */ +alpm_list_t *alpm_option_get_noupgrades(pmhandle_t *handle); +int alpm_option_add_noupgrade(pmhandle_t *handle, const char *pkg); +int alpm_option_set_noupgrades(pmhandle_t *handle, alpm_list_t *noupgrade); +int alpm_option_remove_noupgrade(pmhandle_t *handle, const char *pkg); +/** @} */ -alpm_list_t *alpm_option_get_noupgrades(void); -void alpm_option_add_noupgrade(const char *pkg); -void alpm_option_set_noupgrades(alpm_list_t *noupgrade); -int alpm_option_remove_noupgrade(const char *pkg); +/** @name Accessors to the list of no-extract files. + * These functions modify the list of filenames which should + * be skipped packages which should + * not be upgraded by a sysupgrade operation. + * @{ + */ +alpm_list_t *alpm_option_get_noextracts(pmhandle_t *handle); +int alpm_option_add_noextract(pmhandle_t *handle, const char *pkg); +int alpm_option_set_noextracts(pmhandle_t *handle, alpm_list_t *noextract); +int alpm_option_remove_noextract(pmhandle_t *handle, const char *pkg); +/** @} */ -alpm_list_t *alpm_option_get_noextracts(void); -void alpm_option_add_noextract(const char *pkg); -void alpm_option_set_noextracts(alpm_list_t *noextract); -int alpm_option_remove_noextract(const char *pkg); +/** @name Accessors to the list of ignored packages. + * These functions modify the list of packages that + * should be ignored by a sysupgrade. + * @{ + */ +alpm_list_t *alpm_option_get_ignorepkgs(pmhandle_t *handle); +int alpm_option_add_ignorepkg(pmhandle_t *handle, const char *pkg); +int alpm_option_set_ignorepkgs(pmhandle_t *handle, alpm_list_t *ignorepkgs); +int alpm_option_remove_ignorepkg(pmhandle_t *handle, const char *pkg); +/** @} */ -alpm_list_t *alpm_option_get_ignorepkgs(void); -void alpm_option_add_ignorepkg(const char *pkg); -void alpm_option_set_ignorepkgs(alpm_list_t *ignorepkgs); -int alpm_option_remove_ignorepkg(const char *pkg); +/** @name Accessors to the list of ignored groups. + * These functions modify the list of groups whose packages + * should be ignored by a sysupgrade. + * @{ + */ +alpm_list_t *alpm_option_get_ignoregrps(pmhandle_t *handle); +int alpm_option_add_ignoregrp(pmhandle_t *handle, const char *grp); +int alpm_option_set_ignoregrps(pmhandle_t *handle, alpm_list_t *ignoregrps); +int alpm_option_remove_ignoregrp(pmhandle_t *handle, const char *grp); +/** @} */ -alpm_list_t *alpm_option_get_ignoregrps(void); -void alpm_option_add_ignoregrp(const char *grp); -void alpm_option_set_ignoregrps(alpm_list_t *ignoregrps); -int alpm_option_remove_ignoregrp(const char *grp); +/** Returns the targeted architecture. */ +const char *alpm_option_get_arch(pmhandle_t *handle); +/** Sets the targeted architecture. */ +int alpm_option_set_arch(pmhandle_t *handle, const char *arch); -/** Get/set the targeted architecture. */ -const char *alpm_option_get_arch(void); -void alpm_option_set_arch(const char *arch); +int alpm_option_get_usedelta(pmhandle_t *handle); +int alpm_option_set_usedelta(pmhandle_t *handle, int usedelta); -int alpm_option_get_usedelta(void); -void alpm_option_set_usedelta(int usedelta); +int alpm_option_get_checkspace(pmhandle_t *handle); +int alpm_option_set_checkspace(pmhandle_t *handle, int checkspace); -int alpm_option_get_checkspace(void); -void alpm_option_set_checkspace(int checkspace); +pgp_verify_t alpm_option_get_default_sigverify(pmhandle_t *handle); +int alpm_option_set_default_sigverify(pmhandle_t *handle, pgp_verify_t level); /** @} */ -/** Install reasons - * Why the package was installed. - */ -typedef enum _pmpkgreason_t { - /** Explicitly requested by the user. */ - PM_PKG_REASON_EXPLICIT = 0, - /** Installed as a dependency for another package. */ - PM_PKG_REASON_DEPEND = 1 -} pmpkgreason_t; - /** @addtogroup alpm_api_databases Database Functions * Functions to query and manipulate the database of libalpm. * @{ @@ -215,20 +263,22 @@ typedef enum _pmpkgreason_t { * libalpm functions. * @return a reference to the local database */ -pmdb_t *alpm_option_get_localdb(void); +pmdb_t *alpm_option_get_localdb(pmhandle_t *handle); /** Get the list of sync databases. * Returns a list of pmdb_t structures, one for each registered * sync database. + * @param handle the context handle * @return a reference to an internal list of pmdb_t structures */ -alpm_list_t *alpm_option_get_syncdbs(void); +alpm_list_t *alpm_option_get_syncdbs(pmhandle_t *handle); /** Register a sync database of packages. + * @param handle the context handle * @param treename the name of the sync repository * @return a pmdb_t* on success (the value), NULL on error */ -pmdb_t *alpm_db_register_sync(const char *treename); +pmdb_t *alpm_db_register_sync(pmhandle_t *handle, const char *treename); /** Unregister a package database. * @param db pointer to the package database to unregister @@ -237,9 +287,10 @@ pmdb_t *alpm_db_register_sync(const char *treename); int alpm_db_unregister(pmdb_t *db); /** 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_all(void); +int alpm_db_unregister_all(pmhandle_t *handle); /** Get the name of a package database. * @param db pointer to the package database @@ -247,18 +298,14 @@ int alpm_db_unregister_all(void); */ const char *alpm_db_get_name(const pmdb_t *db); -/** Get a download URL for the package database. - * @param db pointer to the package database - * @return a fully-specified download URL, NULL on error - */ -const char *alpm_db_get_url(const pmdb_t *db); - -/** Set the serverlist of a database. - * @param db database pointer - * @param url url of the server - * @return 0 on success, -1 on error (pm_errno is set accordingly) +/** @name Accessors to the list of servers for a database. + * @{ */ -int alpm_db_setserver(pmdb_t *db, const char *url); +alpm_list_t *alpm_db_get_servers(const pmdb_t *db); +int alpm_db_set_servers(pmdb_t *db, alpm_list_t *servers); +int alpm_db_add_server(pmdb_t *db, const char *url); +int alpm_db_remove_server(pmdb_t *db, const char *url); +/** @} */ int alpm_db_update(int level, pmdb_t *db); @@ -288,10 +335,10 @@ pmgrp_t *alpm_db_readgrp(pmdb_t *db, const char *name); */ alpm_list_t *alpm_db_get_grpcache(pmdb_t *db); -/** Searches a database. +/** Searches a database with regular expressions. * @param db pointer to the package database to search in - * @param needles the list of strings to search for - * @return the list of packages on success, NULL on error + * @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(pmdb_t *db, const alpm_list_t* needles); @@ -313,14 +360,19 @@ int alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason); /** Create a package from a file. * If full is false, the archive is read only until all necessary * metadata is found. If it is true, the entire archive is read, which - * serves as a verfication of integrity and the filelist can be created. + * serves as a verification of integrity and the filelist can be created. + * The allocated structure should be freed using alpm_pkg_free(). + * @param handle the context handle * @param filename location of the package tarball * @param full whether to stop the load after metadata is read or continue - * through the full archive + * through the full archive + * @param check_sig what level of package signature checking to perform on the + * package; note that this must be a '.sig' file type verification * @param pkg address of the package pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg); +int alpm_pkg_load(pmhandle_t *handle, const char *filename, int full, + pgp_verify_t check_sig, pmpkg_t **pkg); /** Free a package. * @param pkg package pointer to free @@ -498,9 +550,9 @@ alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg); */ alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg); -/** Returns the database containing pkg +/** Returns the database containing pkg. * Returns a pointer to the pmdb_t structure the package is - * originating from, or NULL is the package was loaded from a file. + * originating from, or NULL if the package was loaded from a file. * @param pkg a pointer to package * @return a pointer to the DB containing pkg, or NULL. */ @@ -534,6 +586,9 @@ size_t alpm_pkg_changelog_read(void *ptr, size_t size, int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp); +/** Returns whether the package has an install scriptlet. + * @return 0 if FALSE, TRUE otherwise + */ int alpm_pkg_has_scriptlet(pmpkg_t *pkg); /** Returns the size of download. @@ -550,6 +605,15 @@ alpm_list_t *alpm_pkg_unused_deltas(pmpkg_t *pkg); /** @} */ /* + * Signatures + */ + +int alpm_pkg_check_pgp_signature(pmpkg_t *pkg); + +int alpm_db_check_pgp_signature(pmdb_t *db); +int alpm_db_set_pgp_verify(pmdb_t *db, pgp_verify_t verify); + +/* * Deltas */ @@ -726,59 +790,91 @@ typedef void (*alpm_trans_cb_conv)(pmtransconv_t, void *, void *, /** Transaction Progress callback */ typedef void (*alpm_trans_cb_progress)(pmtransprog_t, const char *, int, size_t, size_t); -int alpm_trans_get_flags(void); +/** Returns the bitfield of flags for the current transaction. + * @param handle the context handle + * @return the bitfield of transaction flags + */ +pmtransflag_t alpm_trans_get_flags(pmhandle_t *handle); /** Returns a list of packages added by the transaction. + * @param handle the context handle * @return a list of pmpkg_t structures */ -alpm_list_t * alpm_trans_get_add(void); +alpm_list_t * alpm_trans_get_add(pmhandle_t *handle); /** Returns the list of packages removed by the transaction. + * @param handle the context handle * @return a list of pmpkg_t structures */ -alpm_list_t * alpm_trans_get_remove(void); +alpm_list_t * alpm_trans_get_remove(pmhandle_t *handle); /** Initialize the transaction. + * @param handle the context handle * @param flags flags of the transaction (like nodeps, etc) * @param event event callback function pointer * @param conv question callback function pointer * @param progress progress callback function pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_init(pmtransflag_t flags, +int alpm_trans_init(pmhandle_t *handle, pmtransflag_t flags, alpm_trans_cb_event cb_event, alpm_trans_cb_conv conv, alpm_trans_cb_progress cb_progress); /** Prepare a transaction. + * @param handle the context handle * @param data the address of an alpm_list where a list * of pmdepmissing_t objects is dumped (conflicting packages) * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_prepare(alpm_list_t **data); +int alpm_trans_prepare(pmhandle_t *handle, alpm_list_t **data); /** Commit a transaction. + * @param handle the context handle * @param data the address of an alpm_list where detailed description * of an error can be dumped (ie. list of conflicting files) * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_commit(alpm_list_t **data); +int alpm_trans_commit(pmhandle_t *handle, alpm_list_t **data); /** Interrupt a transaction. + * @param handle the context handle * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_interrupt(void); +int alpm_trans_interrupt(pmhandle_t *handle); /** Release a transaction. + * @param handle the context handle * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_release(void); +int alpm_trans_release(pmhandle_t *handle); /** @} */ /** @name Common Transactions */ /** @{ */ -int alpm_sync_sysupgrade(int enable_downgrade); -int alpm_add_pkg(pmpkg_t *pkg); -int alpm_remove_pkg(pmpkg_t *pkg); + +/** Search for packages to upgrade and add them to the transaction. + * @param handle the context handle + * @param enable_downgrade allow downgrading of packages if the remote version is lower + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_sync_sysupgrade(pmhandle_t *handle, int enable_downgrade); + +/** Add a package to the transaction. + * If the package was loaded by alpm_pkg_load(), it will be freed upon + * alpm_trans_release() invocation. + * @param handle the context handle + * @param pkg the package to add + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_add_pkg(pmhandle_t *handle, pmpkg_t *pkg); + +/** Add a package removal action to the transaction. + * @param handle the context handle + * @param pkg the package to uninstall + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_remove_pkg(pmhandle_t *handle, pmpkg_t *pkg); + /** @} */ /** @addtogroup alpm_api_depends Dependency Functions @@ -803,16 +899,17 @@ typedef enum _pmdepmod_t { PM_DEP_MOD_LT } pmdepmod_t; -alpm_list_t *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, - alpm_list_t *remove, alpm_list_t *upgrade); +alpm_list_t *alpm_checkdeps(pmhandle_t *handle, alpm_list_t *pkglist, + alpm_list_t *remove, alpm_list_t *upgrade, int reversedeps); pmpkg_t *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring); -pmpkg_t *alpm_find_dbs_satisfier(alpm_list_t *dbs, const char *depstring); +pmpkg_t *alpm_find_dbs_satisfier(pmhandle_t *handle, + alpm_list_t *dbs, const char *depstring); const char *alpm_miss_get_target(const pmdepmissing_t *miss); pmdepend_t *alpm_miss_get_dep(pmdepmissing_t *miss); const char *alpm_miss_get_causingpkg(const pmdepmissing_t *miss); -alpm_list_t *alpm_checkconflicts(alpm_list_t *pkglist); +alpm_list_t *alpm_checkconflicts(pmhandle_t *handle, alpm_list_t *pkglist); const char *alpm_conflict_get_package1(pmconflict_t *conflict); const char *alpm_conflict_get_package2(pmconflict_t *conflict); @@ -916,6 +1013,10 @@ enum _pmerrno_t { PM_ERR_PKG_INVALID_NAME, PM_ERR_PKG_INVALID_ARCH, PM_ERR_PKG_REPO_NOT_FOUND, + /* Signatures */ + PM_ERR_SIG_MISSINGDIR, + PM_ERR_SIG_INVALID, + PM_ERR_SIG_UNKNOWN, /* Deltas */ PM_ERR_DLT_INVALID, PM_ERR_DLT_PATCHFAILED, @@ -925,26 +1026,28 @@ enum _pmerrno_t { PM_ERR_FILE_CONFLICTS, /* Misc */ PM_ERR_RETRIEVE, - PM_ERR_WRITE, PM_ERR_INVALID_REGEX, /* External library errors */ PM_ERR_LIBARCHIVE, - PM_ERR_LIBFETCH, - PM_ERR_EXTERNAL_DOWNLOAD + PM_ERR_LIBCURL, + PM_ERR_EXTERNAL_DOWNLOAD, + PM_ERR_GPGME }; -/** The number of the last error that occurred. */ -extern enum _pmerrno_t pm_errno; +/** Returns the current error code from the handle. */ +enum _pmerrno_t alpm_errno(pmhandle_t *handle); /** Returns the string corresponding to an error number. */ -const char *alpm_strerror(int err); - -/** Returns the string corresponding to pm_errno. */ -const char *alpm_strerrorlast(void); +const char *alpm_strerror(enum _pmerrno_t err); /* End of alpm_api_errors */ /** @} */ +pmhandle_t *alpm_initialize(const char *root, const char *dbpath, + enum _pmerrno_t *err); +int alpm_release(pmhandle_t *handle); +const char *alpm_version(void); + /* End of alpm_api */ /** @} */ diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index 42ef367a..c2b30adc 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -20,7 +20,6 @@ #include <stdlib.h> #include <string.h> -#include <stdio.h> /* libalpm */ #include "alpm_list.h" @@ -92,7 +91,7 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) ptr = calloc(1, sizeof(alpm_list_t)); if(ptr == NULL) { - return(list); + return list; } ptr->data = data; @@ -101,7 +100,7 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) /* Special case: the input list is empty */ if(list == NULL) { ptr->prev = ptr; - return(ptr); + return ptr; } lp = alpm_list_last(list); @@ -109,7 +108,7 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) ptr->prev = lp; list->prev = ptr; - return(list); + return list; } /** @@ -124,13 +123,13 @@ alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data) alpm_list_t SYMEXPORT *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_list_fn_cmp fn) { if(!fn || !list) { - return(alpm_list_add(list, data)); + return alpm_list_add(list, data); } else { alpm_list_t *add = NULL, *prev = NULL, *next = list; add = calloc(1, sizeof(alpm_list_t)); if(add == NULL) { - return(list); + return list; } add->data = data; @@ -146,19 +145,19 @@ alpm_list_t SYMEXPORT *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_ add->prev = list->prev; /* list != NULL */ add->next = list; list->prev = add; - return(add); + return add; } else if(next == NULL) { /* another special case: add last element */ add->prev = prev; add->next = NULL; prev->next = add; list->prev = add; - return(list); + return list; } else { add->prev = prev; add->next = next; next->prev = add; prev->next = add; - return(list); + return list; } } } @@ -178,11 +177,11 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second) { alpm_list_t *tmp; - if (first == NULL) { - return(second); + if(first == NULL) { + return second; } - if (second == NULL) { - return(first); + if(second == NULL) { + return first; } /* tmp is the last element of the first list */ tmp = first->prev; @@ -193,7 +192,7 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second) /* set the back reference to the tail */ second->prev = tmp; - return(first); + return first; } /** @@ -209,12 +208,12 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a { alpm_list_t *newlist, *lp; - if (left == NULL) + if(left == NULL) return right; - if (right == NULL) + if(right == NULL) return left; - if (fn(left->data, right->data) <= 0) { + if(fn(left->data, right->data) <= 0) { newlist = left; left = left->next; } @@ -226,8 +225,8 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a newlist->next = NULL; lp = newlist; - while ((left != NULL) && (right != NULL)) { - if (fn(left->data, right->data) <= 0) { + while((left != NULL) && (right != NULL)) { + if(fn(left->data, right->data) <= 0) { lp->next = left; left->prev = lp; left = left->next; @@ -240,11 +239,11 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a lp = lp->next; lp->next = NULL; } - if (left != NULL) { + if(left != NULL) { lp->next = left; left->prev = lp; } - else if (right != NULL) { + else if(right != NULL) { lp->next = right; right->prev = lp; } @@ -257,7 +256,7 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a } newlist->prev = lp; - return(newlist); + return newlist; } /** @@ -271,7 +270,7 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a */ alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, alpm_list_fn_cmp fn) { - if (n > 1) { + 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; @@ -282,7 +281,7 @@ alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, alpm_list_fn right = alpm_list_msort(right, n - (n/2), fn); list = alpm_list_mmerge(left, right, fn); } - return(list); + return list; } /** @@ -298,7 +297,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove_item(alpm_list_t *haystack, alpm_list_t *item) { if(haystack == NULL || item == NULL) { - return(haystack); + return haystack; } if(item == haystack) { @@ -328,7 +327,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove_item(alpm_list_t *haystack, } } - return(haystack); + return haystack; } @@ -352,7 +351,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, } if(needle == NULL) { - return(haystack); + return haystack; } while(i) { @@ -373,7 +372,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, } } - return(haystack); + return haystack; } /** @@ -388,8 +387,8 @@ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, alpm_list_t SYMEXPORT *alpm_list_remove_str(alpm_list_t *haystack, const char *needle, char **data) { - return(alpm_list_remove(haystack, (const void *)needle, - (alpm_list_fn_cmp)strcmp, (void **)data)); + return alpm_list_remove(haystack, (const void *)needle, + (alpm_list_fn_cmp)strcmp, (void **)data); } /** @@ -411,7 +410,7 @@ alpm_list_t SYMEXPORT *alpm_list_remove_dupes(const alpm_list_t *list) } lp = lp->next; } - return(newlist); + return newlist; } /** @@ -429,7 +428,7 @@ alpm_list_t SYMEXPORT *alpm_list_strdup(const alpm_list_t *list) newlist = alpm_list_add(newlist, strdup(lp->data)); lp = lp->next; } - return(newlist); + return newlist; } /** @@ -447,7 +446,7 @@ alpm_list_t SYMEXPORT *alpm_list_copy(const alpm_list_t *list) newlist = alpm_list_add(newlist, lp->data); lp = lp->next; } - return(newlist); + return newlist; } /** @@ -473,7 +472,7 @@ alpm_list_t SYMEXPORT *alpm_list_copy_data(const alpm_list_t *list, lp = lp->next; } } - return(newlist); + return newlist; } /** @@ -489,7 +488,7 @@ alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list) alpm_list_t *newlist = NULL, *backup; if(list == NULL) { - return(NULL); + return NULL; } lp = alpm_list_last(list); @@ -502,7 +501,7 @@ alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list) lp = lp->prev; } list->prev = backup; /* restore tail pointer */ - return(newlist); + return newlist; } /* Accessors */ @@ -517,9 +516,9 @@ alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list) inline alpm_list_t SYMEXPORT *alpm_list_first(const alpm_list_t *list) { if(list) { - return((alpm_list_t*)list); + return (alpm_list_t *)list; } else { - return(NULL); + return NULL; } } @@ -537,7 +536,7 @@ alpm_list_t SYMEXPORT *alpm_list_nth(const alpm_list_t *list, size_t n) while(n--) { i = i->next; } - return((alpm_list_t*)i); + return (alpm_list_t *)i; } /** @@ -550,9 +549,9 @@ alpm_list_t SYMEXPORT *alpm_list_nth(const alpm_list_t *list, size_t n) inline alpm_list_t SYMEXPORT *alpm_list_next(const alpm_list_t *node) { if(node) { - return(node->next); + return node->next; } else { - return(NULL); + return NULL; } } @@ -566,9 +565,9 @@ inline alpm_list_t SYMEXPORT *alpm_list_next(const alpm_list_t *node) alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list) { if(list) { - return(list->prev); + return list->prev; } else { - return(NULL); + return NULL; } } @@ -581,8 +580,8 @@ alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list) */ void SYMEXPORT *alpm_list_getdata(const alpm_list_t *node) { - if(node == NULL) return(NULL); - return(node->data); + if(node == NULL) return NULL; + return node->data; } /* Misc */ @@ -602,7 +601,7 @@ size_t SYMEXPORT alpm_list_count(const alpm_list_t *list) ++i; lp = lp->next; } - return(i); + return i; } /** @@ -620,17 +619,17 @@ void SYMEXPORT *alpm_list_find(const alpm_list_t *haystack, const void *needle, const alpm_list_t *lp = haystack; while(lp) { if(lp->data && fn(lp->data, needle) == 0) { - return(lp->data); + return lp->data; } lp = lp->next; } - return(NULL); + return NULL; } /* trivial helper function for alpm_list_find_ptr */ static int ptr_cmp(const void *p, const void *q) { - return(p != q); + return (p != q); } /** @@ -643,9 +642,10 @@ static int ptr_cmp(const void *p, const void *q) * * @return `needle` if found, NULL otherwise */ -void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, const void *needle) +void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, + const void *needle) { - return(alpm_list_find(haystack, needle, ptr_cmp)); + return alpm_list_find(haystack, needle, ptr_cmp); } /** @@ -659,8 +659,8 @@ void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack, const void *need char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack, const char *needle) { - return((char *)alpm_list_find(haystack, (const void*)needle, - (alpm_list_fn_cmp)strcmp)); + return (char *)alpm_list_find(haystack, (const void *)needle, + (alpm_list_fn_cmp)strcmp); } /** @@ -688,7 +688,7 @@ void SYMEXPORT alpm_list_diff_sorted(const alpm_list_t *left, return; } - while (l != NULL && r != NULL) { + while(l != NULL && r != NULL) { int cmp = fn(l->data, r->data); if(cmp < 0) { if(onlyleft) { @@ -706,13 +706,13 @@ void SYMEXPORT alpm_list_diff_sorted(const alpm_list_t *left, r = r->next; } } - while (l != NULL) { + while(l != NULL) { if(onlyleft) { *onlyleft = alpm_list_add(*onlyleft, l->data); } l = l->next; } - while (r != NULL) { + while(r != NULL) { if(onlyright) { *onlyright = alpm_list_add(*onlyright, r->data); } @@ -745,7 +745,7 @@ alpm_list_t SYMEXPORT *alpm_list_diff(const alpm_list_t *lhs, alpm_list_free(left); alpm_list_free(right); - return(ret); + return ret; } /** @} */ diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c index ca955ca4..6431b286 100644 --- a/lib/libalpm/backup.c +++ b/lib/libalpm/backup.c @@ -47,7 +47,7 @@ static int backup_split(const char *string, char **file, char **hash) /* don't need our dup as the fname wasn't requested, so free it */ FREE(str); } - return(0); + return 0; } *ptr = '\0'; ptr++; @@ -59,21 +59,21 @@ static int backup_split(const char *string, char **file, char **hash) *hash = strdup(ptr); } FREE(str); - return(1); + return 1; } char *_alpm_backup_file(const char *string) { char *file = NULL; backup_split(string, &file, NULL); - return(file); + return file; } char *_alpm_backup_hash(const char *string) { char *hash = NULL; backup_split(string, NULL, &hash); - return(hash); + return hash; } /* Look for a filename in a pmpkg_t.backup list. If we find it, @@ -83,10 +83,8 @@ char *_alpm_needbackup(const char *file, const alpm_list_t *backup) { const alpm_list_t *lp; - ALPM_LOG_FUNC; - if(file == NULL || backup == NULL) { - return(NULL); + return NULL; } /* run through the backup list and parse out the hash for our file */ @@ -101,13 +99,13 @@ char *_alpm_needbackup(const char *file, const alpm_list_t *backup) } if(strcmp(file, filename) == 0) { FREE(filename); - return(hash); + return hash; } FREE(filename); FREE(hash); } - return(NULL); + return NULL; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/base64.c b/lib/libalpm/base64.c new file mode 100644 index 00000000..fa8bec5c --- /dev/null +++ b/lib/libalpm/base64.c @@ -0,0 +1,190 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * Pacman Notes: + * + * Taken from the PolarSSL project at www.polarssl.org under terms of the + * GPL. This is from version 0.14.2 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/base64.h" to "base64.h" + * * removal of SELF_TEST code + */ + +#include "base64.h" + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +/* + * Encode a buffer into base64 format + */ +int base64_encode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ) +{ + int i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + return( 0 ); + + n = (slen << 3) / 6; + + switch( (slen << 3) - (n * 6) ) + { + case 2: n += 3; break; + case 4: n += 2; break; + default: break; + } + + if( *dlen < n + 1 ) + { + *dlen = n + 1; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = (slen / 3) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ((i + 1) < slen) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( (i + 1) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *dlen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int base64_decode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ) +{ + int i, j, n; + unsigned long x; + unsigned char *p; + + for( i = j = n = 0; i < slen; i++ ) + { + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + if( src[i] == '=' && ++j > 2 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + return( 0 ); + + n = ((n * 6) + 7) >> 3; + + if( *dlen < n ) + { + *dlen = n; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = (x << 6) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *dlen = p - dst; + + return( 0 ); +} diff --git a/lib/libalpm/base64.h b/lib/libalpm/base64.h new file mode 100644 index 00000000..0ae9612c --- /dev/null +++ b/lib/libalpm/base64.h @@ -0,0 +1,68 @@ +/** + * \file base64.h + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _BASE64_H +#define _BASE64_H + +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL 0x0010 +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER 0x0012 + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. + * *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_encode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or + * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not + * correct. *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_decode( unsigned char *dst, int *dlen, + const unsigned char *src, int slen ); + +#endif /* base64.h */ diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index d5edf34c..d9a76cc2 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -31,10 +31,6 @@ #include <time.h> #include <limits.h> /* PATH_MAX */ -/* libarchive */ -#include <archive.h> -#include <archive_entry.h> - /* libalpm */ #include "db.h" #include "alpm_list.h" @@ -43,16 +39,10 @@ #include "alpm.h" #include "handle.h" #include "package.h" -#include "group.h" #include "deps.h" -#include "dload.h" - #define LAZY_LOAD(info, errret) \ do { \ - ALPM_LOG_FUNC; \ - ASSERT(handle != NULL, return(errret)); \ - ASSERT(pkg != NULL, return(errret)); \ if(pkg->origin != PKG_FROM_FILE && !(pkg->infolevel & info)) { \ _alpm_local_db_read(pkg->origin_data.db, pkg, info); \ } \ @@ -71,18 +61,6 @@ static const char *_cache_get_filename(pmpkg_t *pkg) return pkg->filename; } -static const char *_cache_get_name(pmpkg_t *pkg) -{ - ASSERT(pkg != NULL, return(NULL)); - return pkg->name; -} - -static const char *_cache_get_version(pmpkg_t *pkg) -{ - ASSERT(pkg != NULL, return(NULL)); - return pkg->version; -} - static const char *_cache_get_desc(pmpkg_t *pkg) { LAZY_LOAD(INFRQ_DESC, NULL); @@ -157,12 +135,6 @@ static alpm_list_t *_cache_get_groups(pmpkg_t *pkg) static int _cache_has_scriptlet(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(-1)); - ASSERT(pkg != NULL, return(-1)); - if(!(pkg->infolevel & INFRQ_SCRIPTLET)) { _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_SCRIPTLET); } @@ -200,19 +172,13 @@ static alpm_list_t *_cache_get_replaces(pmpkg_t *pkg) } /* local packages can not have deltas */ -static alpm_list_t *_cache_get_deltas(pmpkg_t *pkg) +static alpm_list_t *_cache_get_deltas(pmpkg_t UNUSED *pkg) { return NULL; } static alpm_list_t *_cache_get_files(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - if(pkg->origin == PKG_FROM_LOCALDB && !(pkg->infolevel & INFRQ_FILES)) { _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); @@ -222,12 +188,6 @@ static alpm_list_t *_cache_get_files(pmpkg_t *pkg) static alpm_list_t *_cache_get_backup(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - if(pkg->origin == PKG_FROM_LOCALDB && !(pkg->infolevel & INFRQ_FILES)) { _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); @@ -243,15 +203,9 @@ static alpm_list_t *_cache_get_backup(pmpkg_t *pkg) */ static void *_cache_changelog_open(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - char clfile[PATH_MAX]; snprintf(clfile, PATH_MAX, "%s/%s/%s-%s/changelog", - alpm_option_get_dbpath(), + alpm_option_get_dbpath(pkg->handle), alpm_db_get_name(alpm_pkg_get_db(pkg)), alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); @@ -268,17 +222,10 @@ static void *_cache_changelog_open(pmpkg_t *pkg) * @return the number of characters read, or 0 if there is no more data */ static size_t _cache_changelog_read(void *ptr, size_t size, - const pmpkg_t *pkg, const void *fp) -{ - return ( fread(ptr, 1, size, (FILE*)fp) ); -} - -/* -static int _cache_changelog_feof(const pmpkg_t *pkg, void *fp) + const pmpkg_t UNUSED *pkg, const void *fp) { - return( feof((FILE*)fp) ); + return fread(ptr, 1, size, (FILE *)fp); } -*/ /** * Close a package changelog for reading. Similar to fclose in functionality, @@ -287,9 +234,9 @@ static int _cache_changelog_feof(const pmpkg_t *pkg, void *fp) * @param fp a 'file stream' to the package changelog * @return whether closing the package changelog stream was successful */ -static int _cache_changelog_close(const pmpkg_t *pkg, void *fp) +static int _cache_changelog_close(const pmpkg_t UNUSED *pkg, void *fp) { - return( fclose((FILE*)fp) ); + return fclose((FILE *)fp); } @@ -299,8 +246,6 @@ static int _cache_changelog_close(const pmpkg_t *pkg, void *fp) */ static struct pkg_operations local_pkg_ops = { .get_filename = _cache_get_filename, - .get_name = _cache_get_name, - .get_version = _cache_get_version, .get_desc = _cache_get_desc, .get_url = _cache_get_url, .get_builddate = _cache_get_builddate, @@ -334,25 +279,25 @@ static int checkdbdir(pmdb_t *db) const char *path = _alpm_db_path(db); if(stat(path, &buf) != 0) { - _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", path); if(_alpm_makepath(path) != 0) { - RET_ERR(PM_ERR_SYSTEM, -1); + RET_ERR(db->handle, PM_ERR_SYSTEM, -1); } } else if(!S_ISDIR(buf.st_mode)) { - _alpm_log(PM_LOG_WARNING, _("removing invalid database: %s\n"), path); + _alpm_log(db->handle, PM_LOG_WARNING, _("removing invalid database: %s\n"), path); if(unlink(path) != 0 || _alpm_makepath(path) != 0) { - RET_ERR(PM_ERR_SYSTEM, -1); + RET_ERR(db->handle, PM_ERR_SYSTEM, -1); } } - return(0); + return 0; } static int is_dir(const char *path, struct dirent *entry) { #ifdef HAVE_STRUCT_DIRENT_D_TYPE if(entry->d_type != DT_UNKNOWN) { - return(entry->d_type == DT_DIR); + return (entry->d_type == DT_DIR); } #endif { @@ -361,12 +306,12 @@ static int is_dir(const char *path, struct dirent *entry) snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name); - if (!stat(buffer, &sbuf)) { - return(S_ISDIR(sbuf.st_mode)); + if(!stat(buffer, &sbuf)) { + return S_ISDIR(sbuf.st_mode); } } - return(0); + return 0; } static int local_db_populate(pmdb_t *db) @@ -378,10 +323,6 @@ static int local_db_populate(pmdb_t *db) const char *dbpath; DIR *dbdir; - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - dbpath = _alpm_db_path(db); if(dbpath == NULL) { /* pm_errno set in _alpm_db_path() */ @@ -391,12 +332,12 @@ static int local_db_populate(pmdb_t *db) if(dbdir == NULL) { if(errno == ENOENT) { /* no database existing yet is not an error */ - return(0); + return 0; } - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); } if(fstat(dirfd(dbdir), &buf) != 0) { - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); } if(buf.st_nlink >= 2) { est_count = buf.st_nlink; @@ -420,7 +361,7 @@ static int local_db_populate(pmdb_t *db) db->pkgcache = _alpm_pkghash_create(est_count * 2); if(db->pkgcache == NULL){ closedir(dbdir); - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, PM_ERR_MEMORY, -1); } while((ent = readdir(dbdir)) != NULL) { @@ -438,11 +379,11 @@ static int local_db_populate(pmdb_t *db) pkg = _alpm_pkg_new(); if(pkg == NULL) { closedir(dbdir); - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, PM_ERR_MEMORY, -1); } /* split the db entry name */ if(_alpm_splitname(name, pkg) != 0) { - _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), + _alpm_log(db->handle, PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), name); _alpm_pkg_free(pkg); continue; @@ -450,7 +391,7 @@ static int local_db_populate(pmdb_t *db) /* duplicated database entries are not allowed */ if(_alpm_pkghash_find(db->pkgcache, pkg->name)) { - _alpm_log(PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); + _alpm_log(db->handle, PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); _alpm_pkg_free(pkg); continue; } @@ -458,16 +399,17 @@ static int local_db_populate(pmdb_t *db) pkg->origin = PKG_FROM_LOCALDB; pkg->origin_data.db = db; pkg->ops = &local_pkg_ops; + pkg->handle = db->handle; /* explicitly read with only 'BASE' data, accessors will handle the rest */ if(_alpm_local_db_read(db, pkg, INFRQ_BASE) == -1) { - _alpm_log(PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name); + _alpm_log(db->handle, PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name); _alpm_pkg_free(pkg); continue; } /* add to the collection */ - _alpm_log(PM_LOG_DEBUG, "adding '%s' to package cache for db '%s'\n", + _alpm_log(db->handle, PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", pkg->name, db->treename); db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg); count++; @@ -477,7 +419,10 @@ static int local_db_populate(pmdb_t *db) if(count > 0) { db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp); } - return(count); + _alpm_log(db->handle, PM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n", + count, db->treename); + + return count; } /* Note: the return value must be freed by the caller */ @@ -489,9 +434,9 @@ static char *get_pkgpath(pmdb_t *db, pmpkg_t *info) dbpath = _alpm_db_path(db); len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3; - MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL)); + MALLOC(pkgpath, len, RET_ERR(db->handle, PM_ERR_MEMORY, NULL)); sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version); - return(pkgpath); + return pkgpath; } @@ -502,22 +447,17 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) char line[1024]; char *pkgpath = NULL; - ALPM_LOG_FUNC; - - if(db == NULL) { - RET_ERR(PM_ERR_DB_NULL, -1); - } - if(info == NULL || info->name == NULL || info->version == NULL) { - _alpm_log(PM_LOG_DEBUG, "invalid package entry provided to _alpm_local_db_read, skipping\n"); - return(-1); + _alpm_log(db->handle, PM_LOG_DEBUG, + "invalid package entry provided to _alpm_local_db_read, skipping\n"); + return -1; } if(info->origin != PKG_FROM_LOCALDB) { - _alpm_log(PM_LOG_DEBUG, + _alpm_log(db->handle, PM_LOG_DEBUG, "request to read info for a non-local package '%s', skipping...\n", info->name); - return(-1); + return -1; } /* bitmask logic here: @@ -527,9 +467,9 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) * == to inforeq? nope, we need to load more info. */ if((info->infolevel & inforeq) == inforeq) { /* already loaded all of this info, do nothing */ - return(0); + return 0; } - _alpm_log(PM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n", + _alpm_log(db->handle, PM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n", info->name, inforeq); /* clear out 'line', to be certain - and to make valgrind happy */ @@ -539,7 +479,7 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(access(pkgpath, F_OK)) { /* directory doesn't exist or can't be opened */ - _alpm_log(PM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n", info->name, info->version, db->treename); goto error; } @@ -548,7 +488,7 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(inforeq & INFRQ_DESC && !(info->infolevel & INFRQ_DESC)) { snprintf(path, PATH_MAX, "%sdesc", pkgpath); if((fp = fopen(path, "r")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; } while(!feof(fp)) { @@ -561,7 +501,7 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) goto error; } if(strcmp(_alpm_strtrim(line), info->name) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: name " + _alpm_log(db->handle, PM_LOG_ERROR, _("%s database is inconsistent: name " "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%VERSION%") == 0) { @@ -569,7 +509,7 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) goto error; } if(strcmp(_alpm_strtrim(line), info->version) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: version " + _alpm_log(db->handle, PM_LOG_ERROR, _("%s database is inconsistent: version " "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%DESC%") == 0) { @@ -672,7 +612,7 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) if(inforeq & INFRQ_FILES && !(info->infolevel & INFRQ_FILES)) { snprintf(path, PATH_MAX, "%sfiles", pkgpath); if((fp = fopen(path, "r")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); goto error; } while(fgets(line, sizeof(line), fp)) { @@ -707,14 +647,14 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) info->infolevel |= inforeq; free(pkgpath); - return(0); + return 0; error: free(pkgpath); if(fp) { fclose(fp); } - return(-1); + return -1; } int _alpm_local_db_prepare(pmdb_t *db, pmpkg_t *info) @@ -724,21 +664,21 @@ int _alpm_local_db_prepare(pmdb_t *db, pmpkg_t *info) char *pkgpath = NULL; if(checkdbdir(db) != 0) { - return(-1); + return -1; } oldmask = umask(0000); pkgpath = get_pkgpath(db, info); if((retval = mkdir(pkgpath, 0755)) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not create directory %s: %s\n"), + _alpm_log(db->handle, PM_LOG_ERROR, _("could not create directory %s: %s\n"), pkgpath, strerror(errno)); } free(pkgpath); umask(oldmask); - return(retval); + return retval; } int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) @@ -750,10 +690,8 @@ int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) int retval = 0; char *pkgpath = NULL; - ALPM_LOG_FUNC; - if(db == NULL || info == NULL) { - return(-1); + return -1; } pkgpath = get_pkgpath(db, info); @@ -762,16 +700,17 @@ int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) oldmask = umask(0022); if(strcmp(db->treename, "local") != 0) { - return(-1); + return -1; } /* DESC */ if(inforeq & INFRQ_DESC) { - _alpm_log(PM_LOG_DEBUG, "writing %s-%s DESC information back to db\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "writing %s-%s DESC information back to db\n", info->name, info->version); snprintf(path, PATH_MAX, "%sdesc", pkgpath); if((fp = fopen(path, "w")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, PM_LOG_ERROR, _("could not open file %s: %s\n"), + path, strerror(errno)); retval = -1; goto cleanup; } @@ -868,11 +807,12 @@ int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) /* FILES */ if(inforeq & INFRQ_FILES) { - _alpm_log(PM_LOG_DEBUG, "writing %s-%s FILES information back to db\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "writing %s-%s FILES information back to db\n", info->name, info->version); snprintf(path, PATH_MAX, "%sfiles", pkgpath); if((fp = fopen(path, "w")) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno)); + _alpm_log(db->handle, PM_LOG_ERROR, _("could not open file %s: %s\n"), + path, strerror(errno)); retval = -1; goto cleanup; } @@ -905,7 +845,7 @@ cleanup: fclose(fp); } - return(retval); + return retval; } int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info) @@ -913,12 +853,6 @@ int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info) int ret = 0; char *pkgpath = NULL; - ALPM_LOG_FUNC; - - if(db == NULL || info == NULL) { - RET_ERR(PM_ERR_DB_NULL, -1); - } - pkgpath = get_pkgpath(db, info); ret = _alpm_rmrf(pkgpath); @@ -926,7 +860,7 @@ int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info) if(ret != 0) { ret = -1; } - return(ret); + return ret; } static int local_db_version(pmdb_t *db) @@ -938,7 +872,7 @@ static int local_db_version(pmdb_t *db) dbpath = _alpm_db_path(db); if(dbpath == NULL) { - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); } dbdir = opendir(dbpath); if(dbdir == NULL) { @@ -947,7 +881,7 @@ static int local_db_version(pmdb_t *db) version = 2; goto done; } else { - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); } } @@ -977,8 +911,8 @@ done: closedir(dbdir); } - _alpm_log(PM_LOG_DEBUG, "local database version %d\n", version); - return(version); + _alpm_log(db->handle, PM_LOG_DEBUG, "local database version %d\n", version); + return version; } struct db_operations local_db_ops = { @@ -987,22 +921,21 @@ struct db_operations local_db_ops = { .version = local_db_version, }; -pmdb_t *_alpm_db_register_local(void) +pmdb_t *_alpm_db_register_local(pmhandle_t *handle) { pmdb_t *db; - ALPM_LOG_FUNC; - - _alpm_log(PM_LOG_DEBUG, "registering local database\n"); + _alpm_log(handle, PM_LOG_DEBUG, "registering local database\n"); db = _alpm_db_new("local", 1); if(db == NULL) { - RET_ERR(PM_ERR_DB_CREATE, NULL); + return NULL; } db->ops = &local_db_ops; + db->handle = handle; handle->db_local = db; - return(db); + return db; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 6dfddd61..a0261d07 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -20,10 +20,8 @@ #include "config.h" -#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <limits.h> #include <errno.h> /* libarchive */ @@ -32,8 +30,10 @@ /* libalpm */ #include "alpm_list.h" +#include "alpm.h" #include "util.h" #include "log.h" +#include "handle.h" #include "package.h" #include "deps.h" /* _alpm_splitdep */ @@ -45,38 +45,36 @@ */ static void *_package_changelog_open(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - ASSERT(pkg != NULL, return(NULL)); + ASSERT(pkg != NULL, return NULL); struct archive *archive = NULL; struct archive_entry *entry; const char *pkgfile = pkg->origin_data.file; if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE, NULL); + RET_ERR(pkg->handle, PM_ERR_LIBARCHIVE, NULL); } archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - if (archive_read_open_filename(archive, pkgfile, + if(archive_read_open_filename(archive, pkgfile, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); + RET_ERR(pkg->handle, PM_ERR_PKG_OPEN, 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); + return archive; } } /* we didn't find a changelog */ archive_read_finish(archive); errno = ENOENT; - return(NULL); + return NULL; } /** @@ -89,26 +87,17 @@ static void *_package_changelog_open(pmpkg_t *pkg) * @return the number of characters read, or 0 if there is no more data */ static size_t _package_changelog_read(void *ptr, size_t size, - const pmpkg_t *pkg, const void *fp) + const pmpkg_t UNUSED *pkg, const void *fp) { - ssize_t sret = archive_read_data((struct archive*)fp, ptr, size); + ssize_t sret = archive_read_data((struct archive *)fp, ptr, size); /* Report error (negative values) */ if(sret < 0) { - pm_errno = PM_ERR_LIBARCHIVE; - return(0); + RET_ERR(pkg->handle, PM_ERR_LIBARCHIVE, 0); } else { - return((size_t)sret); + return (size_t)sret; } } -/* -static int _package_changelog_feof(const pmpkg_t *pkg, void *fp) -{ - // note: this doesn't quite work, no feof in libarchive - return( archive_read_data((struct archive*)fp, NULL, 0) ); -} -*/ - /** * Close a package changelog for reading. Similar to fclose in functionality, * except that the 'file stream' is from an archive. @@ -116,9 +105,9 @@ static int _package_changelog_feof(const pmpkg_t *pkg, void *fp) * @param fp a 'file stream' to the package changelog * @return whether closing the package changelog stream was successful */ -static int _package_changelog_close(const pmpkg_t *pkg, void *fp) +static int _package_changelog_close(const pmpkg_t UNUSED *pkg, void *fp) { - return( archive_read_finish((struct archive *)fp) ); + return archive_read_finish((struct archive *)fp); } /** Package file operations struct accessor. We implement this as a method @@ -137,7 +126,7 @@ static struct pkg_operations *get_file_pkg_ops(void) file_pkg_ops.changelog_close = _package_changelog_close; file_pkg_ops_initialized = 1; } - return(&file_pkg_ops); + return &file_pkg_ops; } /** @@ -145,23 +134,21 @@ static struct pkg_operations *get_file_pkg_ops(void) * @param archive the archive to read from, pointed at the .PKGINFO entry * @param newpkg an empty pmpkg_t struct to fill with package info * - * @return 0 on success, 1 on error + * @return 0 on success, -1 on error */ -static int parse_descfile(struct archive *a, pmpkg_t *newpkg) +static int parse_descfile(pmhandle_t *handle, struct archive *a, pmpkg_t *newpkg) { char *ptr = NULL; char *key = NULL; - int linenum = 0; + int ret, linenum = 0; struct archive_read_buffer buf; - ALPM_LOG_FUNC; - memset(&buf, 0, sizeof(buf)); /* 512K for a line length seems reasonable */ buf.max_line_size = 512 * 1024; /* loop until we reach EOF or other error */ - while(_alpm_archive_fgets(a, &buf) == ARCHIVE_OK) { + while((ret = _alpm_archive_fgets(a, &buf)) == ARCHIVE_OK) { char *line = _alpm_strtrim(buf.line); linenum++; @@ -171,33 +158,33 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) ptr = line; key = strsep(&ptr, "="); if(key == NULL || ptr == NULL) { - _alpm_log(PM_LOG_DEBUG, "%s: syntax error in description file line %d\n", + _alpm_log(handle, PM_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); if(strcmp(key, "pkgname") == 0) { - STRDUP(newpkg->name, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->name, ptr, return -1); newpkg->name_hash = _alpm_hash_sdbm(newpkg->name); } else if(strcmp(key, "pkgbase") == 0) { /* not used atm */ } else if(strcmp(key, "pkgver") == 0) { - STRDUP(newpkg->version, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->version, ptr, return -1); } else if(strcmp(key, "pkgdesc") == 0) { - STRDUP(newpkg->desc, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->desc, ptr, return -1); } else if(strcmp(key, "group") == 0) { newpkg->groups = alpm_list_add(newpkg->groups, strdup(ptr)); } else if(strcmp(key, "url") == 0) { - STRDUP(newpkg->url, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->url, ptr, return -1); } else if(strcmp(key, "license") == 0) { newpkg->licenses = alpm_list_add(newpkg->licenses, strdup(ptr)); } else if(strcmp(key, "builddate") == 0) { newpkg->builddate = _alpm_parsedate(ptr); } else if(strcmp(key, "packager") == 0) { - STRDUP(newpkg->packager, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->packager, ptr, return -1); } else if(strcmp(key, "arch") == 0) { - STRDUP(newpkg->arch, ptr, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(newpkg->arch, ptr, return -1); } else if(strcmp(key, "size") == 0) { /* size in the raw package is uncompressed (installed) size */ newpkg->isize = atol(ptr); @@ -219,64 +206,93 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) } else if(strcmp(key, "makepkgopt") == 0) { /* not used atm */ } else { - _alpm_log(PM_LOG_DEBUG, "%s: unknown key '%s' in description file line %d\n", + _alpm_log(handle, PM_LOG_DEBUG, "%s: unknown key '%s' in description file line %d\n", newpkg->name ? newpkg->name : "error", key, linenum); } } line[0] = '\0'; } + if(ret != ARCHIVE_EOF) { + _alpm_log(handle, PM_LOG_DEBUG, "error parsing package descfile\n"); + return -1; + } - return(0); + return 0; } /** * Load a package and create the corresponding pmpkg_t struct. + * @param handle the context handle * @param pkgfile path to the package file * @param full whether to stop the load after metadata is read or continue * through the full archive * @return An information filled pmpkg_t struct */ -static pmpkg_t *pkg_load(const char *pkgfile, int full) +pmpkg_t *_alpm_pkg_load_internal(pmhandle_t *handle, const char *pkgfile, + int full, const char *md5sum, const char *base64_sig, + pgp_verify_t check_sig) { - int ret = ARCHIVE_OK; + int ret; int config = 0; struct archive *archive; struct archive_entry *entry; pmpkg_t *newpkg = NULL; struct stat st; - ALPM_LOG_FUNC; - if(pkgfile == NULL || strlen(pkgfile) == 0) { - RET_ERR(PM_ERR_WRONG_ARGS, NULL); + RET_ERR(handle, PM_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, PM_ERR_MEMORY, NULL); + } + newpkg->filename = strdup(pkgfile); + newpkg->size = st.st_size; + } else { + /* couldn't stat the pkgfile, return an error */ + RET_ERR(handle, PM_ERR_PKG_OPEN, NULL); + } + + /* first steps- validate the package file */ + _alpm_log(handle, PM_LOG_DEBUG, "md5sum: %s\n", md5sum); + if(md5sum) { + _alpm_log(handle, PM_LOG_DEBUG, "checking md5sum for %s\n", pkgfile); + if(_alpm_test_md5sum(pkgfile, md5sum) != 0) { + alpm_pkg_free(newpkg); + RET_ERR(handle, PM_ERR_PKG_INVALID, NULL); + } } - if(stat(pkgfile, &st) != 0) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); + _alpm_log(handle, PM_LOG_DEBUG, "base64_sig: %s\n", base64_sig); + if(check_sig != PM_PGP_VERIFY_NEVER) { + _alpm_log(handle, PM_LOG_DEBUG, "checking signature for %s\n", pkgfile); + ret = _alpm_gpgme_checksig(handle, pkgfile, base64_sig); + if((check_sig == PM_PGP_VERIFY_ALWAYS && ret != 0) || + (check_sig == PM_PGP_VERIFY_OPTIONAL && ret == 1)) { + alpm_pkg_free(newpkg); + RET_ERR(handle, PM_ERR_SIG_INVALID, NULL); + } } + /* next- try to create an archive object to read in the package */ if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE, NULL); + alpm_pkg_free(newpkg); + RET_ERR(handle, PM_ERR_LIBARCHIVE, NULL); } archive_read_support_compression_all(archive); archive_read_support_format_all(archive); - if (archive_read_open_filename(archive, pkgfile, + if(archive_read_open_filename(archive, pkgfile, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - RET_ERR(PM_ERR_PKG_OPEN, NULL); - } - - newpkg = _alpm_pkg_new(); - if(newpkg == NULL) { - archive_read_finish(archive); - RET_ERR(PM_ERR_MEMORY, NULL); + alpm_pkg_free(newpkg); + RET_ERR(handle, PM_ERR_PKG_OPEN, NULL); } - newpkg->filename = strdup(pkgfile); - newpkg->size = st.st_size; - - _alpm_log(PM_LOG_DEBUG, "starting package load for %s\n", pkgfile); + _alpm_log(handle, PM_LOG_DEBUG, "starting package load for %s\n", pkgfile); /* If full is false, only read through the archive until we find our needed * metadata. If it is true, read through the entire archive, which serves @@ -286,17 +302,17 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) if(strcmp(entry_name, ".PKGINFO") == 0) { /* parse the info file */ - if(parse_descfile(archive, newpkg) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not parse package description file in %s\n"), + if(parse_descfile(handle, archive, newpkg) != 0) { + _alpm_log(handle, PM_LOG_ERROR, _("could not parse package description file in %s\n"), pkgfile); goto pkg_invalid; } if(newpkg->name == NULL || strlen(newpkg->name) == 0) { - _alpm_log(PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile); + _alpm_log(handle, PM_LOG_ERROR, _("missing package name in %s\n"), pkgfile); goto pkg_invalid; } if(newpkg->version == NULL || strlen(newpkg->version) == 0) { - _alpm_log(PM_LOG_ERROR, _("missing package version in %s\n"), pkgfile); + _alpm_log(handle, PM_LOG_ERROR, _("missing package version in %s\n"), pkgfile); goto pkg_invalid; } config = 1; @@ -312,9 +328,9 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) } if(archive_read_data_skip(archive)) { - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("error while reading package %s: %s\n"), pkgfile, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE; + handle->pm_errno = PM_ERR_LIBARCHIVE; goto error; } @@ -325,14 +341,14 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) } if(ret != ARCHIVE_EOF && ret != ARCHIVE_OK) { /* An error occured */ - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("error while reading package %s: %s\n"), pkgfile, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE; + handle->pm_errno = PM_ERR_LIBARCHIVE; goto error; } if(!config) { - _alpm_log(PM_LOG_ERROR, _("missing package metadata in %s\n"), pkgfile); + _alpm_log(handle, PM_LOG_ERROR, _("missing package metadata in %s\n"), pkgfile); goto pkg_invalid; } @@ -340,13 +356,13 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) /* internal fields for package struct */ newpkg->origin = PKG_FROM_FILE; - /* TODO eventually kill/move this? */ newpkg->origin_data.file = strdup(pkgfile); newpkg->ops = get_file_pkg_ops(); + newpkg->handle = handle; if(full) { /* "checking for conflicts" requires a sorted list, ensure that here */ - _alpm_log(PM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile); + _alpm_log(handle, PM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile); newpkg->files = alpm_list_msort(newpkg->files, alpm_list_count(newpkg->files), _alpm_str_cmp); newpkg->infolevel = INFRQ_ALL; @@ -356,33 +372,30 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) newpkg->infolevel = INFRQ_BASE | INFRQ_DESC; } - return(newpkg); + return newpkg; pkg_invalid: - pm_errno = PM_ERR_PKG_INVALID; + handle->pm_errno = PM_ERR_PKG_INVALID; error: _alpm_pkg_free(newpkg); archive_read_finish(archive); - return(NULL); + return NULL; } -int SYMEXPORT alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg) +int SYMEXPORT alpm_pkg_load(pmhandle_t *handle, const char *filename, int full, + pgp_verify_t check_sig, pmpkg_t **pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(filename != NULL && strlen(filename) != 0, - RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(pkg != NULL, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); - *pkg = pkg_load(filename, full); + *pkg = _alpm_pkg_load_internal(handle, filename, full, NULL, NULL, check_sig); if(*pkg == NULL) { /* pm_errno is set by pkg_load */ - return(-1); + return -1; } - return(0); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index c440cd6b..bb109284 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -20,8 +20,7 @@ #include "config.h" -#include <errno.h> -#include <limits.h> +#include <sys/stat.h> /* libarchive */ #include <archive.h> @@ -38,6 +37,34 @@ #include "deps.h" #include "dload.h" +static char *get_sync_dir(pmhandle_t *handle) +{ + const char *dbpath = alpm_option_get_dbpath(handle); + size_t len = strlen(dbpath) + 6; + char *syncpath; + struct stat buf; + + MALLOC(syncpath, len, RET_ERR(handle, PM_ERR_MEMORY, NULL)); + sprintf(syncpath, "%s%s", dbpath, "sync/"); + + if(stat(syncpath, &buf) != 0) { + _alpm_log(handle, PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", + syncpath); + if(_alpm_makepath(syncpath) != 0) { + free(syncpath); + RET_ERR(handle, PM_ERR_SYSTEM, NULL); + } + } else if(!S_ISDIR(buf.st_mode)) { + _alpm_log(handle, PM_LOG_WARNING, _("removing invalid file: %s\n"), syncpath); + if(unlink(syncpath) != 0 || _alpm_makepath(syncpath) != 0) { + free(syncpath); + RET_ERR(handle, PM_ERR_SYSTEM, NULL); + } + } + + return syncpath; +} + /** Update a package database * * An update of the package database \a db will be attempted. Unless @@ -79,71 +106,78 @@ */ int SYMEXPORT alpm_db_update(int force, pmdb_t *db) { - char *dbfile, *syncpath; - const char *dbpath; - struct stat buf; - size_t len; - int ret; + char *syncpath; + alpm_list_t *i; + int ret = -1; mode_t oldmask; - - ALPM_LOG_FUNC; + pmhandle_t *handle; + pgp_verify_t check_sig; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(db != NULL && db != handle->db_local, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - - if(!alpm_list_find_ptr(handle->dbs_sync, db)) { - RET_ERR(PM_ERR_DB_NOT_FOUND, -1); - } - - len = strlen(db->treename) + 4; - MALLOC(dbfile, len, RET_ERR(PM_ERR_MEMORY, -1)); - sprintf(dbfile, "%s.db", db->treename); - - dbpath = alpm_option_get_dbpath(); - len = strlen(dbpath) + 6; - MALLOC(syncpath, len, RET_ERR(PM_ERR_MEMORY, -1)); - sprintf(syncpath, "%s%s", dbpath, "sync/"); + ASSERT(db != NULL, return -1); + handle = db->handle; + handle->pm_errno = 0; + ASSERT(db != handle->db_local, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); + ASSERT(db->servers != NULL, RET_ERR(handle, PM_ERR_SERVER_NONE, -1)); /* make sure we have a sane umask */ oldmask = umask(0022); - if(stat(syncpath, &buf) != 0) { - _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", - syncpath); - if(_alpm_makepath(syncpath) != 0) { - free(dbfile); - free(syncpath); - RET_ERR(PM_ERR_SYSTEM, -1); + syncpath = get_sync_dir(handle); + if(!syncpath) { + return -1; + } + check_sig = _alpm_db_get_sigverify_level(db); + + for(i = db->servers; i; i = i->next) { + const char *server = i->data; + char *fileurl; + size_t len; + int sig_ret = 0; + + /* print server + filename into a buffer (leave space for .sig) */ + len = strlen(server) + strlen(db->treename) + 9; + CALLOC(fileurl, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, -1)); + snprintf(fileurl, len, "%s/%s.db", server, db->treename); + + ret = _alpm_download(handle, fileurl, syncpath, force, 0, 0); + + if(ret == 0 && (check_sig == PM_PGP_VERIFY_ALWAYS || + check_sig == PM_PGP_VERIFY_OPTIONAL)) { + int errors_ok = (check_sig == PM_PGP_VERIFY_OPTIONAL); + /* if we downloaded a DB, we want the .sig from the same server */ + snprintf(fileurl, len, "%s/%s.db.sig", server, db->treename); + + sig_ret = _alpm_download(handle, fileurl, syncpath, 1, 0, errors_ok); + /* errors_ok suppresses error messages, but not the return code */ + sig_ret = errors_ok ? 0 : sig_ret; } - } else if(!S_ISDIR(buf.st_mode)) { - _alpm_log(PM_LOG_WARNING, _("removing invalid file: %s\n"), syncpath); - if(unlink(syncpath) != 0 || _alpm_makepath(syncpath) != 0) { - free(dbfile); - free(syncpath); - RET_ERR(PM_ERR_SYSTEM, -1); + + FREE(fileurl); + if(ret != -1 && sig_ret != -1) { + break; } } - ret = _alpm_download_single_file(dbfile, db->servers, syncpath, force); - free(dbfile); - free(syncpath); - umask(oldmask); - if(ret == 1) { /* files match, do nothing */ - pm_errno = 0; - return(1); + handle->pm_errno = 0; + goto cleanup; } else if(ret == -1) { /* pm_errno was set by the download code */ - _alpm_log(PM_LOG_DEBUG, "failed to sync db: %s\n", alpm_strerrorlast()); - return(-1); + _alpm_log(handle, PM_LOG_DEBUG, "failed to sync db: %s\n", + alpm_strerror(handle->pm_errno)); + goto cleanup; } /* Cache needs to be rebuilt */ _alpm_db_free_pkgcache(db); - return(0); +cleanup: + + free(syncpath); + umask(oldmask); + return ret; } /* Forward decl so I don't reorganize the whole file right now */ @@ -206,7 +240,7 @@ static size_t estimate_package_count(struct stat *st, struct archive *archive) /* assume it is at least somewhat compressed */ per_package = 200; } - return((size_t)(st->st_size / per_package) + 1); + return (size_t)((st->st_size / per_package) + 1); } static int sync_db_populate(pmdb_t *db) @@ -219,12 +253,8 @@ static int sync_db_populate(pmdb_t *db) struct archive_entry *entry; pmpkg_t *pkg = NULL; - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - if((archive = archive_read_new()) == NULL) { - RET_ERR(PM_ERR_LIBARCHIVE, -1); + RET_ERR(db->handle, PM_ERR_LIBARCHIVE, -1); } archive_read_support_compression_all(archive); @@ -236,24 +266,24 @@ static int sync_db_populate(pmdb_t *db) return -1; } - _alpm_log(PM_LOG_DEBUG, "opening database archive %s\n", dbpath); + _alpm_log(db->handle, PM_LOG_DEBUG, "opening database archive %s\n", dbpath); if(archive_read_open_filename(archive, dbpath, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), dbpath, + _alpm_log(db->handle, PM_LOG_ERROR, _("could not open file %s: %s\n"), dbpath, archive_error_string(archive)); archive_read_finish(archive); - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); } if(stat(dbpath, &buf) != 0) { - RET_ERR(PM_ERR_DB_OPEN, -1); + RET_ERR(db->handle, PM_ERR_DB_OPEN, -1); } est_count = estimate_package_count(&buf, archive); /* initialize hash at 66% full */ db->pkgcache = _alpm_pkghash_create(est_count * 3 / 2); if(db->pkgcache == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, PM_ERR_MEMORY, -1); } while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { @@ -267,37 +297,47 @@ static int sync_db_populate(pmdb_t *db) pkg = _alpm_pkg_new(); if(pkg == NULL) { archive_read_finish(archive); - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, PM_ERR_MEMORY, -1); } name = archive_entry_pathname(entry); if(_alpm_splitname(name, pkg) != 0) { - _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), + _alpm_log(db->handle, PM_LOG_ERROR, _("invalid name for database entry '%s'\n"), name); _alpm_pkg_free(pkg); + pkg = NULL; continue; } /* duplicated database entries are not allowed */ if(_alpm_pkghash_find(db->pkgcache, pkg->name)) { - _alpm_log(PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); + _alpm_log(db->handle, PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name); _alpm_pkg_free(pkg); + pkg = NULL; continue; } pkg->origin = PKG_FROM_SYNCDB; - pkg->ops = &default_pkg_ops; pkg->origin_data.db = db; + pkg->ops = &default_pkg_ops; + pkg->handle = db->handle; /* add to the collection */ - _alpm_log(PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", + _alpm_log(db->handle, PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", pkg->name, db->treename); db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg); count++; } else { /* we have desc, depends or deltas - parse it */ - sync_db_read(db, archive, entry, pkg); + if(sync_db_read(db, archive, entry, pkg) != 0) { + _alpm_log(db->handle, PM_LOG_ERROR, + _("could not parse package '%s' description file from db '%s'\n"), + pkg->name, db->treename); + _alpm_pkg_free(pkg); + pkg = NULL; + continue; + } } } @@ -305,8 +345,10 @@ static int sync_db_populate(pmdb_t *db) db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp); } archive_read_finish(archive); + _alpm_log(db->handle, PM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n", + count, db->treename); - return(count); + return count; } #define READ_NEXT(s) do { \ @@ -330,26 +372,19 @@ static int sync_db_populate(pmdb_t *db) static int sync_db_read(pmdb_t *db, struct archive *archive, struct archive_entry *entry, pmpkg_t *likely_pkg) { - const char *entryname = NULL, *filename; + const char *entryname, *filename; char *pkgname, *p, *q; pmpkg_t *pkg; struct archive_read_buffer buf; - ALPM_LOG_FUNC; - - if(db == NULL) { - RET_ERR(PM_ERR_DB_NULL, -1); - } - - if(entry != NULL) { - entryname = archive_entry_pathname(entry); - } + entryname = archive_entry_pathname(entry); if(entryname == NULL) { - _alpm_log(PM_LOG_DEBUG, "invalid archive entry provided to _alpm_sync_db_read, skipping\n"); - return(-1); + _alpm_log(db->handle, PM_LOG_DEBUG, + "invalid archive entry provided to _alpm_sync_db_read, skipping\n"); + return -1; } - _alpm_log(PM_LOG_FUNCTION, "loading package data from archive entry %s\n", + _alpm_log(db->handle, PM_LOG_FUNCTION, "loading package data from archive entry %s\n", entryname); memset(&buf, 0, sizeof(buf)); @@ -357,7 +392,7 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, buf.max_line_size = 512 * 1024; /* get package and db file names */ - STRDUP(pkgname, entryname, RET_ERR(PM_ERR_MEMORY, -1)); + STRDUP(pkgname, entryname, RET_ERR(db->handle, PM_ERR_MEMORY, -1)); p = pkgname + strlen(pkgname); for(q = --p; *q && *q != '/'; q--); filename = q + 1; @@ -370,31 +405,32 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, pkg = likely_pkg; } else { if(db->pkgcache == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); + RET_ERR(db->handle, PM_ERR_MEMORY, -1); } pkg = _alpm_pkghash_find(db->pkgcache, pkgname); } if(pkg == NULL) { - _alpm_log(PM_LOG_DEBUG, "package %s not found in %s sync database", + _alpm_log(db->handle, PM_LOG_DEBUG, "package %s not found in %s sync database", pkgname, db->treename); - return(-1); + return -1; } if(strcmp(filename, "desc") == 0 || strcmp(filename, "depends") == 0 || strcmp(filename, "deltas") == 0) { - while(_alpm_archive_fgets(archive, &buf) == ARCHIVE_OK) { + int ret; + while((ret = _alpm_archive_fgets(archive, &buf)) == ARCHIVE_OK) { char *line = _alpm_strtrim(buf.line); if(strcmp(line, "%NAME%") == 0) { READ_NEXT(line); if(strcmp(line, pkg->name) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: name " + _alpm_log(db->handle, PM_LOG_ERROR, _("%s database is inconsistent: name " "mismatch on package %s\n"), db->treename, pkg->name); } } else if(strcmp(line, "%VERSION%") == 0) { READ_NEXT(line); if(strcmp(line, pkg->version) != 0) { - _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: version " + _alpm_log(db->handle, PM_LOG_ERROR, _("%s database is inconsistent: version " "mismatch on package %s\n"), db->treename, pkg->name); } } else if(strcmp(line, "%FILENAME%") == 0) { @@ -434,8 +470,7 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, /* we don't do anything with this value right now */ READ_NEXT(line); } else if(strcmp(line, "%PGPSIG%") == 0) { - /* we don't do anything with this value right now */ - READ_NEXT(line); + READ_AND_STORE(pkg->base64_sig); } else if(strcmp(line, "%REPLACES%") == 0) { READ_AND_STORE_ALL(pkg->replaces); } else if(strcmp(line, "%DEPENDS%") == 0) { @@ -460,22 +495,28 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, } } } + if(ret != ARCHIVE_EOF) { + goto error; + } } else if(strcmp(filename, "files") == 0) { /* currently do nothing with this file */ } else { /* unknown database file */ - _alpm_log(PM_LOG_DEBUG, "unknown database file: %s\n", filename); + _alpm_log(db->handle, PM_LOG_DEBUG, "unknown database file: %s\n", filename); } + FREE(pkgname); + return 0; + error: + _alpm_log(db->handle, PM_LOG_DEBUG, "error parsing database file: %s\n", filename); FREE(pkgname); - /* TODO: return 0 always? */ - return(0); + return -1; } -static int sync_db_version(pmdb_t *db) +static int sync_db_version(pmdb_t UNUSED *db) { - return(2); + return 2; } struct db_operations sync_db_ops = { @@ -484,31 +525,21 @@ struct db_operations sync_db_ops = { .version = sync_db_version, }; -pmdb_t *_alpm_db_register_sync(const char *treename) +pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename) { pmdb_t *db; - alpm_list_t *i; - - ALPM_LOG_FUNC; - - for(i = handle->dbs_sync; i; i = i->next) { - pmdb_t *sdb = i->data; - if(strcmp(treename, sdb->treename) == 0) { - _alpm_log(PM_LOG_DEBUG, "attempt to re-register the '%s' database, using existing\n", sdb->treename); - return sdb; - } - } - _alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename); + _alpm_log(handle, PM_LOG_DEBUG, "registering sync database '%s'\n", treename); db = _alpm_db_new(treename, 0); if(db == NULL) { - RET_ERR(PM_ERR_DB_CREATE, NULL); + RET_ERR(handle, PM_ERR_DB_CREATE, NULL); } db->ops = &sync_db_ops; + db->handle = handle; handle->dbs_sync = alpm_list_add(handle->dbs_sync, db); - return(db); + return db; } diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 6faced16..a6bbe093 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -40,20 +40,18 @@ #include "log.h" #include "deps.h" -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, +static pmconflict_t *conflict_new(const char *package1, const char *package2, const char *reason) { pmconflict_t *conflict; - ALPM_LOG_FUNC; + MALLOC(conflict, sizeof(pmconflict_t), return NULL); - MALLOC(conflict, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->package1, package1, return NULL); + STRDUP(conflict->package2, package2, return NULL); + STRDUP(conflict->reason, reason, return NULL); - STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->reason, reason, RET_ERR(PM_ERR_MEMORY, NULL)); - - return(conflict); + return conflict; } void _alpm_conflict_free(pmconflict_t *conflict) @@ -67,13 +65,13 @@ void _alpm_conflict_free(pmconflict_t *conflict) pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict) { pmconflict_t *newconflict; - CALLOC(newconflict, 1, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(newconflict, 1, sizeof(pmconflict_t), ); - STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(newconflict->reason, conflict->reason, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newconflict->package1, conflict->package1, return NULL); + STRDUP(newconflict->package2, conflict->package2, return NULL); + STRDUP(newconflict->reason, conflict->reason, return NULL); - return(newconflict); + return newconflict; } static int conflict_isin(pmconflict_t *needle, alpm_list_t *haystack) @@ -82,37 +80,41 @@ static int conflict_isin(pmconflict_t *needle, alpm_list_t *haystack) const char *npkg1 = needle->package1; const char *npkg2 = needle->package2; - ALPM_LOG_FUNC; - for(i = haystack; i; i = i->next) { pmconflict_t *conflict = i->data; const char *cpkg1 = conflict->package1; const char *cpkg2 = conflict->package2; if((strcmp(cpkg1, npkg1) == 0 && strcmp(cpkg2, npkg2) == 0) || (strcmp(cpkg1, npkg2) == 0 && strcmp(cpkg2, npkg1) == 0)) { - return(1); + return 1; } } - return(0); + return 0; } -/** Adds the pkg1/pkg2 conflict to the baddeps list - * @param *baddeps list to add conflict to +/** Adds the pkg1/pkg2 conflict to the baddeps list. + * @param handle the context handle + * @param baddeps list to add conflict to * @param pkg1 first package * @param pkg2 package causing conflict + * @param reason reason for this conflict */ -static void add_conflict(alpm_list_t **baddeps, const char *pkg1, - const char *pkg2, const char *reason) +static int add_conflict(pmhandle_t *handle, alpm_list_t **baddeps, + const char *pkg1, const char *pkg2, const char *reason) { - pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2, reason); - _alpm_log(PM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", + pmconflict_t *conflict = conflict_new(pkg1, pkg2, reason); + if(!conflict) { + return -1; + } + _alpm_log(handle, PM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", pkg1, pkg2, reason); - if(conflict && !conflict_isin(conflict, *baddeps)) { + if(!conflict_isin(conflict, *baddeps)) { *baddeps = alpm_list_add(*baddeps, conflict); } else { _alpm_conflict_free(conflict); } + return 0; } /** Check if packages from list1 conflict with packages from list2. @@ -121,14 +123,16 @@ static void add_conflict(alpm_list_t **baddeps, const char *pkg1, * If a conflict (pkg1, pkg2) is found, it is added to the baddeps list * in this order if order >= 0, or reverse order (pkg2,pkg1) otherwise. * + * @param handle the context handle * @param list1 first list of packages * @param list2 second list of packages - * @param *baddeps list to store conflicts + * @param baddeps list to store conflicts * @param order if >= 0 the conflict order is preserved, if < 0 it's reversed */ -static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, +static void check_conflict(pmhandle_t *handle, + alpm_list_t *list1, alpm_list_t *list2, alpm_list_t **baddeps, int order) { - alpm_list_t *i, *j, *k; + alpm_list_t *i; if(!baddeps) { return; @@ -136,9 +140,11 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, for(i = list1; i; i = i->next) { pmpkg_t *pkg1 = i->data; const char *pkg1name = alpm_pkg_get_name(pkg1); + alpm_list_t *j; for(j = alpm_pkg_get_conflicts(pkg1); j; j = j->next) { const char *conflict = j->data; + alpm_list_t *k; pmdepend_t *parsed_conflict = _alpm_splitdep(conflict); for(k = list2; k; k = k->next) { @@ -152,9 +158,9 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, if(_alpm_depcmp(pkg2, parsed_conflict)) { if(order >= 0) { - add_conflict(baddeps, pkg1name, pkg2name, conflict); + add_conflict(handle, baddeps, pkg1name, pkg2name, conflict); } else { - add_conflict(baddeps, pkg2name, pkg1name, conflict); + add_conflict(handle, baddeps, pkg2name, pkg1name, conflict); } } } @@ -164,16 +170,14 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, } /* Check for inter-conflicts */ -alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages) +alpm_list_t *_alpm_innerconflicts(pmhandle_t *handle, alpm_list_t *packages) { alpm_list_t *baddeps = NULL; - ALPM_LOG_FUNC; + _alpm_log(handle, PM_LOG_DEBUG, "check targets vs targets\n"); + check_conflict(handle, packages, packages, &baddeps, 0); - _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); - check_conflict(packages, packages, &baddeps, 0); - - return(baddeps); + return baddeps; } /* Check for target vs (db - target) conflicts @@ -184,85 +188,55 @@ alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages) { alpm_list_t *baddeps = NULL; - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } alpm_list_t *dblist = alpm_list_diff(_alpm_db_get_pkgcache(db), packages, _alpm_pkg_cmp); /* two checks to be done here for conflicts */ - _alpm_log(PM_LOG_DEBUG, "check targets vs db\n"); - check_conflict(packages, dblist, &baddeps, 1); - _alpm_log(PM_LOG_DEBUG, "check db vs targets\n"); - check_conflict(dblist, packages, &baddeps, -1); + _alpm_log(db->handle, PM_LOG_DEBUG, "check targets vs db\n"); + check_conflict(db->handle, packages, dblist, &baddeps, 1); + _alpm_log(db->handle, PM_LOG_DEBUG, "check db vs targets\n"); + check_conflict(db->handle, dblist, packages, &baddeps, -1); alpm_list_free(dblist); - return(baddeps); + return baddeps; } /** Check the package conflicts in a database * + * @param handle the context handle * @param pkglist the list of packages to check * @return an alpm_list_t of pmconflict_t */ -alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_list_t *pkglist) { - return(_alpm_innerconflicts(pkglist)); -} - -/* Returns a alpm_list_t* of file conflicts. - * Hooray for set-intersects! - * Pre-condition: both lists are sorted! - */ -static alpm_list_t *chk_fileconflicts(alpm_list_t *filesA, alpm_list_t *filesB) +alpm_list_t SYMEXPORT *alpm_checkconflicts(pmhandle_t *handle, + alpm_list_t *pkglist) { - alpm_list_t *ret = NULL; - alpm_list_t *pA = filesA, *pB = filesB; - - while(pA && pB) { - const char *strA = pA->data; - const char *strB = pB->data; - /* skip directories, we don't care about dir conflicts */ - if(strA[strlen(strA)-1] == '/') { - pA = pA->next; - } else if(strB[strlen(strB)-1] == '/') { - pB = pB->next; - } else { - int cmp = strcmp(strA, strB); - if(cmp < 0) { - /* item only in filesA, ignore it */ - pA = pA->next; - } else if(cmp > 0) { - /* item only in filesB, ignore it */ - pB = pB->next; - } else { - /* item in both, record it */ - ret = alpm_list_add(ret, strdup(strA)); - pA = pA->next; - pB = pB->next; - } - } - } - - return(ret); + CHECK_HANDLE(handle, return NULL); + return _alpm_innerconflicts(handle, pkglist); } -/* Returns a alpm_list_t* of files that are in filesA but *NOT* in filesB - * This is an 'A minus B' set operation - * Pre-condition: both lists are sorted! +static const int DIFFERENCE = 0; +static const int INTERSECT = 1; +/* Returns a set operation on the provided two lists of files. + * Pre-condition: both lists are sorted! + * + * Operations: + * DIFFERENCE - a difference operation is performed. filesA - filesB. + * INTERSECT - an intersection operation is performed. filesA & filesB. */ -static alpm_list_t *chk_filedifference(alpm_list_t *filesA, alpm_list_t *filesB) +static alpm_list_t *filelist_operation(alpm_list_t *filesA, alpm_list_t *filesB, + int operation) { alpm_list_t *ret = NULL; alpm_list_t *pA = filesA, *pB = filesB; - /* if both filesA and filesB have entries, do this loop */ while(pA && pB) { const char *strA = pA->data; const char *strB = pB->data; - /* skip directories, we don't care about dir conflicts */ + /* skip directories, we don't care about them */ if(strA[strlen(strA)-1] == '/') { pA = pA->next; } else if(strB[strlen(strB)-1] == '/') { @@ -270,21 +244,26 @@ static alpm_list_t *chk_filedifference(alpm_list_t *filesA, alpm_list_t *filesB) } else { int cmp = strcmp(strA, strB); if(cmp < 0) { - /* item only in filesA, record it */ - ret = alpm_list_add(ret, strdup(strA)); + if(operation == DIFFERENCE) { + /* item only in filesA, qualifies as a difference */ + ret = alpm_list_add(ret, strdup(strA)); + } pA = pA->next; } else if(cmp > 0) { - /* item only in fileB, but this means nothing */ pB = pB->next; } else { - /* item in both, ignore it */ + if(operation == INTERSECT) { + /* item in both, qualifies as an intersect */ + ret = alpm_list_add(ret, strdup(strA)); + } pA = pA->next; pB = pB->next; } } } - /* ensure we have completely emptied pA */ - while(pA) { + + /* if doing a difference, ensure we have completely emptied pA */ + while(operation == DIFFERENCE && pA) { const char *strA = pA->data; /* skip directories */ if(strA[strlen(strA)-1] != '/') { @@ -293,7 +272,7 @@ static alpm_list_t *chk_filedifference(alpm_list_t *filesA, alpm_list_t *filesB) pA = pA->next; } - return(ret); + return ret; } /* Adds pmfileconflict_t to a conflicts list. Pass the conflicts list, type (either @@ -301,40 +280,42 @@ static alpm_list_t *chk_filedifference(alpm_list_t *filesA, alpm_list_t *filesB) * two package names or one package name and NULL. This is a wrapper for former * functionality that was done inline. */ -static alpm_list_t *add_fileconflict(alpm_list_t *conflicts, - pmfileconflicttype_t type, const char *filestr, - const char* name1, const char* name2) +static alpm_list_t *add_fileconflict(pmhandle_t *handle, + alpm_list_t *conflicts, pmfileconflicttype_t type, const char *filestr, + const char *name1, const char *name2) { pmfileconflict_t *conflict; - MALLOC(conflict, sizeof(pmfileconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + MALLOC(conflict, sizeof(pmfileconflict_t), goto error); conflict->type = type; - STRDUP(conflict->target, name1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->file, filestr, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->target, name1, goto error); + STRDUP(conflict->file, filestr, goto error); if(name2) { - STRDUP(conflict->ctarget, name2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->ctarget, name2, goto error); } else { - conflict->ctarget = ""; + STRDUP(conflict->ctarget, "", goto error); } conflicts = alpm_list_add(conflicts, conflict); - _alpm_log(PM_LOG_DEBUG, "found file conflict %s, packages %s and %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "found file conflict %s, packages %s and %s\n", filestr, name1, name2 ? name2 : "(filesystem)"); - return(conflicts); + return conflicts; + +error: + RET_ERR(handle, PM_ERR_MEMORY, conflicts); } void _alpm_fileconflict_free(pmfileconflict_t *conflict) { - if(strlen(conflict->ctarget) > 0) { - FREE(conflict->ctarget); - } - FREE(conflict->file);; + FREE(conflict->ctarget); + FREE(conflict->file); FREE(conflict->target); FREE(conflict); } -static int dir_belongsto_pkg(char *dirpath, pmpkg_t *pkg) +static int dir_belongsto_pkg(const char *root, const char *dirpath, + pmpkg_t *pkg) { struct dirent *ent = NULL; struct stat sbuf; @@ -342,10 +323,10 @@ static int dir_belongsto_pkg(char *dirpath, pmpkg_t *pkg) char abspath[PATH_MAX]; DIR *dir; - snprintf(abspath, PATH_MAX, "%s%s", handle->root, dirpath); + snprintf(abspath, PATH_MAX, "%s%s", root, dirpath); dir = opendir(abspath); if(dir == NULL) { - return(1); + return 1; } while((ent = readdir(dir)) != NULL) { const char *name = ent->d_name; @@ -354,44 +335,43 @@ static int dir_belongsto_pkg(char *dirpath, pmpkg_t *pkg) continue; } snprintf(path, PATH_MAX, "%s/%s", dirpath, name); - snprintf(abspath, PATH_MAX, "%s%s", handle->root, path); + snprintf(abspath, PATH_MAX, "%s%s", root, path); if(stat(abspath, &sbuf) != 0) { continue; } if(S_ISDIR(sbuf.st_mode)) { - if(dir_belongsto_pkg(path, pkg)) { + if(dir_belongsto_pkg(root, path, pkg)) { continue; } else { closedir(dir); - return(0); + return 0; } } else { if(alpm_list_find_str(alpm_pkg_get_files(pkg), path)) { continue; } else { closedir(dir); - return(0); + return 0; } } } closedir(dir); - return(1); + return 1; } /* Find file conflicts that may occur during the transaction with two checks: * 1: check every target against every target * 2: check every target against the filesystem */ -alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, +alpm_list_t *_alpm_db_find_fileconflicts(pmhandle_t *handle, alpm_list_t *upgrade, alpm_list_t *remove) { alpm_list_t *i, *j, *conflicts = NULL; size_t numtargs = alpm_list_count(upgrade); size_t current; + pmtrans_t *trans = handle->trans; - ALPM_LOG_FUNC; - - if(db == NULL || upgrade == NULL || trans == NULL) { - return(NULL); + if(!upgrade) { + return NULL; } /* TODO this whole function needs a huge change, which hopefully will @@ -399,9 +379,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, * here as we do when we actually extract files in add.c with our 12 * different cases. */ for(current = 0, i = upgrade; i; i = i->next, current++) { - alpm_list_t *k, *tmpfiles = NULL; + alpm_list_t *k, *tmpfiles; pmpkg_t *p1, *p2, *dbpkg; - char path[PATH_MAX+1]; + char path[PATH_MAX]; p1 = i->data; if(!p1) { @@ -412,47 +392,55 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", percent, numtargs, current); /* CHECK 1: check every target against every target */ - _alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "searching for file conflicts: %s\n", alpm_pkg_get_name(p1)); for(j = i->next; j; j = j->next) { + alpm_list_t *common_files; p2 = j->data; if(!p2) { continue; } - tmpfiles = chk_fileconflicts(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2)); + common_files = filelist_operation(alpm_pkg_get_files(p1), + alpm_pkg_get_files(p2), INTERSECT); - if(tmpfiles) { - for(k = tmpfiles; k; k = k->next) { + if(common_files) { + for(k = common_files; k; k = k->next) { snprintf(path, PATH_MAX, "%s%s", handle->root, (char *)k->data); - conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_TARGET, path, + conflicts = add_fileconflict(handle, conflicts, + PM_FILECONFLICT_TARGET, path, alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)); + if(handle->pm_errno == PM_ERR_MEMORY) { + FREELIST(conflicts); + FREELIST(common_files); + return NULL; + } } - FREELIST(tmpfiles); + FREELIST(common_files); } } - /* declarations for second check */ - struct stat lsbuf, sbuf; - char *filestr = NULL; - /* CHECK 2: check every target against the filesystem */ - _alpm_log(PM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", p1->name); - dbpkg = _alpm_db_get_pkgfromcache(db, p1->name); + _alpm_log(handle, PM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", + p1->name); + dbpkg = _alpm_db_get_pkgfromcache(handle->db_local, p1->name); /* Do two different checks here. If the package is currently installed, * then only check files that are new in the new package. If the package - * is not currently installed, then simply stat the whole filelist */ + * is not currently installed, then simply stat the whole filelist. Note + * that the former list needs to be freed while the latter list should NOT + * be freed. */ if(dbpkg) { /* older ver of package currently installed */ - tmpfiles = chk_filedifference(alpm_pkg_get_files(p1), - alpm_pkg_get_files(dbpkg)); + tmpfiles = filelist_operation(alpm_pkg_get_files(p1), + alpm_pkg_get_files(dbpkg), DIFFERENCE); } else { /* no version of package currently installed */ - tmpfiles = alpm_list_strdup(alpm_pkg_get_files(p1)); + tmpfiles = alpm_pkg_get_files(p1); } for(j = tmpfiles; j; j = j->next) { - filestr = j->data; + struct stat lsbuf; + const char *filestr = j->data; snprintf(path, PATH_MAX, "%s%s", handle->root, filestr); @@ -460,19 +448,21 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, if(_alpm_lstat(path, &lsbuf) != 0) { continue; } - stat(path, &sbuf); if(path[strlen(path)-1] == '/') { + struct stat sbuf; if(S_ISDIR(lsbuf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); + _alpm_log(handle, PM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); continue; - } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, + } + stat(path, &sbuf); + if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { + _alpm_log(handle, PM_LOG_DEBUG, "%s is a symlink to a dir, hopefully not a conflict\n", path); continue; } } - _alpm_log(PM_LOG_DEBUG, "checking possible conflict: %s\n", path); + _alpm_log(handle, PM_LOG_DEBUG, "checking possible conflict: %s\n", path); int resolved_conflict = 0; /* have we acted on this conflict? */ @@ -480,7 +470,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, for(k = remove; k && !resolved_conflict; k = k->next) { pmpkg_t *rempkg = k->data; if(rempkg && alpm_list_find_str(alpm_pkg_get_files(rempkg), filestr)) { - _alpm_log(PM_LOG_DEBUG, "local file will be removed, not a conflict: %s\n", filestr); + _alpm_log(handle, PM_LOG_DEBUG, + "local file will be removed, not a conflict: %s\n", filestr); resolved_conflict = 1; } } @@ -491,15 +482,17 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, if(!p2 || strcmp(p1->name, p2->name) == 0) { continue; } - pmpkg_t *localp2 = _alpm_db_get_pkgfromcache(db, p2->name); + pmpkg_t *localp2 = _alpm_db_get_pkgfromcache(handle->db_local, p2->name); /* localp2->files will be removed (target conflicts are handled by CHECK 1) */ if(localp2 && alpm_list_find_str(alpm_pkg_get_files(localp2), filestr)) { /* skip removal of file, but not add. this will prevent a second * package from removing the file when it was already installed * by its new owner (whether the file is in backup array or not */ - trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(filestr)); - _alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s\n", filestr); + handle->trans->skip_remove = + alpm_list_add(handle->trans->skip_remove, strdup(filestr)); + _alpm_log(handle, PM_LOG_DEBUG, + "file changed packages, adding to remove skiplist: %s\n", filestr); resolved_conflict = 1; } } @@ -509,114 +502,91 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *dir = malloc(strlen(filestr) + 2); sprintf(dir, "%s/", filestr); if(alpm_list_find_str(alpm_pkg_get_files(dbpkg),dir)) { - _alpm_log(PM_LOG_DEBUG, "check if all files in %s belongs to %s\n", + _alpm_log(handle, PM_LOG_DEBUG, + "check if all files in %s belongs to %s\n", dir, dbpkg->name); - resolved_conflict = dir_belongsto_pkg(filestr, dbpkg); + resolved_conflict = dir_belongsto_pkg(handle->root, filestr, dbpkg); } free(dir); } if(!resolved_conflict && dbpkg) { - char *rpath = calloc(PATH_MAX+1, sizeof(char)); + char *rpath = calloc(PATH_MAX, sizeof(char)); if(!realpath(path, rpath)) { - FREE(rpath); + free(rpath); continue; } char *filestr = rpath + strlen(handle->root); - if(alpm_list_find_str(alpm_pkg_get_files(dbpkg),filestr)) { + if(alpm_list_find_str(alpm_pkg_get_files(dbpkg), filestr)) { resolved_conflict = 1; } free(rpath); } if(!resolved_conflict) { - _alpm_log(PM_LOG_DEBUG, "file found in conflict: %s\n", path); - conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_FILESYSTEM, - path, p1->name, NULL); + conflicts = add_fileconflict(handle, conflicts, + PM_FILECONFLICT_FILESYSTEM, path, p1->name, NULL); + if(handle->pm_errno == PM_ERR_MEMORY) { + FREELIST(conflicts); + if(dbpkg) { + /* only freed if it was generated from filelist_operation() */ + FREELIST(tmpfiles); + } + return NULL; + } } } - FREELIST(tmpfiles); + if(dbpkg) { + /* only freed if it was generated from filelist_operation() */ + FREELIST(tmpfiles); + } } PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", 100, numtargs, current); - return(conflicts); + return conflicts; } const char SYMEXPORT *alpm_conflict_get_package1(pmconflict_t *conflict) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - + ASSERT(conflict != NULL, return NULL); return conflict->package1; } const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - + ASSERT(conflict != NULL, return NULL); return conflict->package2; } const char SYMEXPORT *alpm_conflict_get_reason(pmconflict_t *conflict) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - + ASSERT(conflict != NULL, return NULL); return conflict->reason; } const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - + ASSERT(conflict != NULL, return NULL); return conflict->target; } pmfileconflicttype_t SYMEXPORT alpm_fileconflict_get_type(pmfileconflict_t *conflict) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(-1)); - ASSERT(conflict != NULL, return(-1)); - + ASSERT(conflict != NULL, return -1); return conflict->type; } const char SYMEXPORT *alpm_fileconflict_get_file(pmfileconflict_t *conflict) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - + ASSERT(conflict != NULL, return NULL); return conflict->file; } const char SYMEXPORT *alpm_fileconflict_get_ctarget(pmfileconflict_t *conflict) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - + ASSERT(conflict != NULL, return NULL); return conflict->ctarget; } + /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 418d3f61..7a3784a2 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -37,13 +37,12 @@ struct __pmfileconflict_t { char *ctarget; }; -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, const char *reason); pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict); void _alpm_conflict_free(pmconflict_t *conflict); -alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages); +alpm_list_t *_alpm_innerconflicts(pmhandle_t *handle, alpm_list_t *packages); alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages); -alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, - alpm_list_t *upgrade, alpm_list_t *remove); +alpm_list_t *_alpm_db_find_fileconflicts(pmhandle_t *handle, + alpm_list_t *upgrade, alpm_list_t *remove); void _alpm_fileconflict_free(pmfileconflict_t *conflict); diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 1a3168b4..c3a7abd2 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -26,11 +26,8 @@ #include <stdio.h> #include <stdlib.h> -#include <errno.h> #include <string.h> -#include <sys/stat.h> #include <regex.h> -#include <time.h> /* libalpm */ #include "db.h" @@ -48,17 +45,16 @@ */ /** Register a sync database of packages. */ -pmdb_t SYMEXPORT *alpm_db_register_sync(const char *treename) +pmdb_t SYMEXPORT *alpm_db_register_sync(pmhandle_t *handle, const char *treename) { - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, NULL)); - ASSERT(treename != NULL && strlen(treename) != 0, RET_ERR(PM_ERR_WRONG_ARGS, NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(treename != NULL && strlen(treename) != 0, + RET_ERR(handle, PM_ERR_WRONG_ARGS, NULL)); /* Do not register a database if a transaction is on-going */ - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, NULL)); + ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, NULL)); - return(_alpm_db_register_sync(treename)); + return _alpm_db_register_sync(handle, treename); } /* Helper function for alpm_db_unregister{_all} */ @@ -68,22 +64,20 @@ void _alpm_db_unregister(pmdb_t *db) return; } - _alpm_log(PM_LOG_DEBUG, "unregistering database '%s'\n", db->treename); + _alpm_log(db->handle, PM_LOG_DEBUG, "unregistering database '%s'\n", db->treename); _alpm_db_free(db); } /** Unregister all package databases. */ -int SYMEXPORT alpm_db_unregister_all(void) +int SYMEXPORT alpm_db_unregister_all(pmhandle_t *handle) { alpm_list_t *i; pmdb_t *db; - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); /* Do not unregister a database if a transaction is on-going */ - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); + ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, -1)); /* unregister all sync dbs */ for(i = handle->dbs_sync; i; i = i->next) { @@ -92,21 +86,21 @@ int SYMEXPORT alpm_db_unregister_all(void) i->data = NULL; } FREELIST(handle->dbs_sync); - return(0); + return 0; } /** Unregister a package database. */ int SYMEXPORT alpm_db_unregister(pmdb_t *db) { int found = 0; - - ALPM_LOG_FUNC; + pmhandle_t *handle; /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(db != NULL, return -1); /* Do not unregister a database if a transaction is on-going */ - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); + handle = db->handle; + handle->pm_errno = 0; + ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, -1)); if(db == handle->db_local) { handle->db_local = NULL; @@ -125,175 +119,196 @@ int SYMEXPORT alpm_db_unregister(pmdb_t *db) } if(!found) { - RET_ERR(PM_ERR_DB_NOT_FOUND, -1); + RET_ERR(handle, PM_ERR_DB_NOT_FOUND, -1); } db->ops->unregister(db); - return(0); + return 0; +} + +/** Get the serverlist of a database. */ +alpm_list_t SYMEXPORT *alpm_db_get_servers(const pmdb_t *db) +{ + ASSERT(db != NULL, return NULL); + return db->servers; } /** Set the serverlist of a database. */ -int SYMEXPORT alpm_db_setserver(pmdb_t *db, const char *url) +int SYMEXPORT alpm_db_set_servers(pmdb_t *db, alpm_list_t *servers) +{ + ASSERT(db != NULL, return -1); + if(db->servers) FREELIST(db->servers); + db->servers = servers; + return 0; +} + +static char *sanitize_url(const char *url) { - alpm_list_t *i; - int found = 0; char *newurl; - size_t len = 0; + size_t len = strlen(url); - ALPM_LOG_FUNC; + STRDUP(newurl, url, return NULL); + /* strip the trailing slash if one exists */ + if(newurl[len - 1] == '/') { + newurl[len - 1] = '\0'; + } + return newurl; +} - /* Sanity checks */ - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); +/** Add a download server to a database. + * @param db database pointer + * @param url url of the server + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_db_add_server(pmdb_t *db, const char *url) +{ + char *newurl; - for(i = handle->dbs_sync; i && !found; i = i->next) { - pmdb_t *sdb = i->data; - if(strcmp(db->treename, sdb->treename) == 0) { - found = 1; - } - } - if(!found) { - RET_ERR(PM_ERR_DB_NOT_FOUND, -1); - } + /* Sanity checks */ + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; + ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, PM_ERR_WRONG_ARGS, -1)); - if(url) { - len = strlen(url); - } - if(len) { - newurl = strdup(url); - /* strip the trailing slash if one exists */ - if(newurl[len - 1] == '/') { - newurl[len - 1] = '\0'; - } - db->servers = alpm_list_add(db->servers, newurl); - _alpm_log(PM_LOG_DEBUG, "adding new server URL to database '%s': %s\n", - db->treename, newurl); - } else { - FREELIST(db->servers); - _alpm_log(PM_LOG_DEBUG, "serverlist flushed for '%s'\n", db->treename); + newurl = sanitize_url(url); + if(!newurl) { + return -1; } + db->servers = alpm_list_add(db->servers, newurl); + _alpm_log(db->handle, PM_LOG_DEBUG, "adding new server URL to database '%s': %s\n", + db->treename, newurl); - return(0); + return 0; } -/** Get the name of a package database. */ -const char SYMEXPORT *alpm_db_get_name(const pmdb_t *db) +/** Remove a download server from a database. + * @param db database pointer + * @param url url of the server + * @return 0 on success, 1 on server not present, + * -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_db_remove_server(pmdb_t *db, const char *url) { - ALPM_LOG_FUNC; + char *newurl, *vdata = NULL; /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; + ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, PM_ERR_WRONG_ARGS, -1)); + + newurl = sanitize_url(url); + if(!newurl) { + return -1; + } + db->servers = alpm_list_remove_str(db->servers, newurl, &vdata); + free(newurl); + if(vdata) { + _alpm_log(db->handle, PM_LOG_DEBUG, "removed server URL from database '%s': %s\n", + db->treename, newurl); + free(vdata); + return 0; + } - return db->treename; + return 1; } - -/** Get a download URL for the package database. */ -const char SYMEXPORT *alpm_db_get_url(const pmdb_t *db) +/** Set the verify gpg signature option for a database. + * @param db database pointer + * @param verify enum pgp_verify_t + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int SYMEXPORT alpm_db_set_pgp_verify(pmdb_t *db, pgp_verify_t verify) { - char *url; - - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - ASSERT(db->servers != NULL, return(NULL)); + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; - url = (char*)db->servers->data; + db->pgp_verify = verify; + _alpm_log(db->handle, PM_LOG_DEBUG, "adding VerifySig option to database '%s': %d\n", + db->treename, verify); - return(url); + return 0; } +/** Get the name of a package database. */ +const char SYMEXPORT *alpm_db_get_name(const pmdb_t *db) +{ + ASSERT(db != NULL, return NULL); + return db->treename; +} /** Get a package entry from a package database. */ pmpkg_t SYMEXPORT *alpm_db_get_pkg(pmdb_t *db, const char *name) { - ALPM_LOG_FUNC; + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; + ASSERT(name != NULL && strlen(name) != 0, + RET_ERR(db->handle, PM_ERR_WRONG_ARGS, NULL)); - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - ASSERT(name != NULL && strlen(name) != 0, return(NULL)); - - return(_alpm_db_get_pkgfromcache(db, name)); + return _alpm_db_get_pkgfromcache(db, name); } /** Get the package cache of a package database. */ alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(pmdb_t *db) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - - return(_alpm_db_get_pkgcache(db)); + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; + return _alpm_db_get_pkgcache(db); } /** Get a group entry from a package database. */ pmgrp_t SYMEXPORT *alpm_db_readgrp(pmdb_t *db, const char *name) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - ASSERT(name != NULL && strlen(name) != 0, return(NULL)); + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; + ASSERT(name != NULL && strlen(name) != 0, + RET_ERR(db->handle, PM_ERR_WRONG_ARGS, NULL)); - return(_alpm_db_get_grpfromcache(db, name)); + return _alpm_db_get_grpfromcache(db, name); } /** Get the group cache of a package database. */ alpm_list_t SYMEXPORT *alpm_db_get_grpcache(pmdb_t *db) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; - return(_alpm_db_get_grpcache(db)); + return _alpm_db_get_grpcache(db); } /** Searches a database. */ alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles) { - ALPM_LOG_FUNC; + ASSERT(db != NULL, return NULL); + db->handle->pm_errno = 0; - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(db != NULL, return(NULL)); - - return(_alpm_db_search(db, needles)); + return _alpm_db_search(db, needles); } /** Set install reason for a package in db. */ int SYMEXPORT alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(db != NULL && name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; + /* TODO assert db == db_local ? shouldn't need a db param at all here... */ + ASSERT(name != NULL, RET_ERR(db->handle, PM_ERR_WRONG_ARGS, -1)); pmpkg_t *pkg = _alpm_db_get_pkgfromcache(db, name); if(pkg == NULL) { - RET_ERR(PM_ERR_PKG_NOT_FOUND, -1); + RET_ERR(db->handle, PM_ERR_PKG_NOT_FOUND, -1); } - _alpm_log(PM_LOG_DEBUG, "setting install reason %u for %s/%s\n", reason, db->treename, name); + _alpm_log(db->handle, PM_LOG_DEBUG, "setting install reason %u for %s/%s\n", reason, db->treename, name); if(alpm_pkg_get_reason(pkg) == reason) { /* we are done */ - return(0); + return 0; } /* set reason (in pkgcache) */ pkg->reason = reason; /* write DESC */ if(_alpm_local_db_write(db, pkg, INFRQ_DESC)) { - RET_ERR(PM_ERR_DB_WRITE, -1); + RET_ERR(db->handle, PM_ERR_DB_WRITE, -1); } - return(0); + return 0; } /** @} */ @@ -302,19 +317,16 @@ pmdb_t *_alpm_db_new(const char *treename, int is_local) { pmdb_t *db; - ALPM_LOG_FUNC; - - CALLOC(db, 1, sizeof(pmdb_t), RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(db->treename, treename, RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(db, 1, sizeof(pmdb_t), return NULL); + STRDUP(db->treename, treename, return NULL); db->is_local = is_local; + db->pgp_verify = PM_PGP_VERIFY_UNKNOWN; - return(db); + return db; } void _alpm_db_free(pmdb_t *db) { - ALPM_LOG_FUNC; - /* cleanup pkgcache */ _alpm_db_free_pkgcache(db); /* cleanup server list */ @@ -329,47 +341,61 @@ void _alpm_db_free(pmdb_t *db) const char *_alpm_db_path(pmdb_t *db) { if(!db) { - return(NULL); + return NULL; } if(!db->_path) { const char *dbpath; size_t pathsize; - dbpath = alpm_option_get_dbpath(); + dbpath = alpm_option_get_dbpath(db->handle); if(!dbpath) { - _alpm_log(PM_LOG_ERROR, _("database path is undefined\n")); - RET_ERR(PM_ERR_DB_OPEN, NULL); + _alpm_log(db->handle, PM_LOG_ERROR, _("database path is undefined\n")); + RET_ERR(db->handle, PM_ERR_DB_OPEN, NULL); } if(db->is_local) { pathsize = strlen(dbpath) + strlen(db->treename) + 2; - CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(db->_path, 1, pathsize, RET_ERR(db->handle, PM_ERR_MEMORY, NULL)); sprintf(db->_path, "%s%s/", dbpath, db->treename); } else { pathsize = strlen(dbpath) + 5 + strlen(db->treename) + 4; - CALLOC(db->_path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(db->_path, 1, pathsize, RET_ERR(db->handle, PM_ERR_MEMORY, NULL)); /* all sync DBs now reside in the sync/ subdir of the dbpath */ sprintf(db->_path, "%ssync/%s.db", dbpath, db->treename); } - _alpm_log(PM_LOG_DEBUG, "database path for tree %s set to %s\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "database path for tree %s set to %s\n", db->treename, db->_path); } - return(db->_path); + return db->_path; } int _alpm_db_version(pmdb_t *db) { if(!db) { - return(-1); + return -1; } - return(db->ops->version(db)); + return db->ops->version(db); +} + +char *_alpm_db_sig_path(pmdb_t *db) +{ + char *sigpath; + size_t len; + const char *dbfile = _alpm_db_path(db); + if(!db || !dbfile) { + return NULL; + } + len = strlen(dbfile) + strlen(".sig") + 1; + CALLOC(sigpath, len, sizeof(char), RET_ERR(db->handle, PM_ERR_MEMORY, NULL)); + sprintf(sigpath, "%s.sig", dbfile); + return sigpath; } int _alpm_db_cmp(const void *d1, const void *d2) { pmdb_t *db1 = (pmdb_t *)d1; pmdb_t *db2 = (pmdb_t *)d2; - return(strcmp(db1->treename, db2->treename)); + return strcmp(db1->treename, db2->treename); } alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) @@ -379,8 +405,6 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) /* copy the pkgcache- we will free the list var after each needle */ alpm_list_t *list = alpm_list_copy(_alpm_db_get_pkgcache(db)); - ALPM_LOG_FUNC; - for(i = needles; i; i = i->next) { char *targ; regex_t reg; @@ -390,10 +414,10 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) } ret = NULL; targ = i->data; - _alpm_log(PM_LOG_DEBUG, "searching for target '%s'\n", targ); + _alpm_log(db->handle, PM_LOG_DEBUG, "searching for target '%s'\n", targ); if(regcomp(®, targ, REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE) != 0) { - RET_ERR(PM_ERR_INVALID_REGEX, NULL); + RET_ERR(db->handle, PM_ERR_INVALID_REGEX, NULL); } for(j = list; j; j = j->next) { @@ -407,7 +431,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) matched = name; } /* check desc */ - else if (desc && regexec(®, desc, 0, 0, 0) == 0) { + else if(desc && regexec(®, desc, 0, 0, 0) == 0) { matched = desc; } /* TODO: should we be doing this, and should we print something @@ -415,7 +439,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) if(!matched) { /* check provides */ for(k = alpm_pkg_get_provides(pkg); k; k = k->next) { - if (regexec(®, k->data, 0, 0, 0) == 0) { + if(regexec(®, k->data, 0, 0, 0) == 0) { matched = k->data; break; } @@ -424,7 +448,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) if(!matched) { /* check groups */ for(k = alpm_pkg_get_groups(pkg); k; k = k->next) { - if (regexec(®, k->data, 0, 0, 0) == 0) { + if(regexec(®, k->data, 0, 0, 0) == 0) { matched = k->data; break; } @@ -432,7 +456,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) } if(matched != NULL) { - _alpm_log(PM_LOG_DEBUG, " search target '%s' matched '%s'\n", + _alpm_log(db->handle, PM_LOG_DEBUG, " search target '%s' matched '%s'\n", targ, matched); ret = alpm_list_add(ret, pkg); } @@ -445,7 +469,7 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) regfree(®); } - return(ret); + return ret; } /* Returns a new package cache from db. @@ -453,34 +477,30 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles) */ int _alpm_db_load_pkgcache(pmdb_t *db) { - ALPM_LOG_FUNC; - if(db == NULL) { - return(-1); + return -1; } _alpm_db_free_pkgcache(db); - _alpm_log(PM_LOG_DEBUG, "loading package cache for repository '%s'\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "loading package cache for repository '%s'\n", db->treename); if(db->ops->populate(db) == -1) { - _alpm_log(PM_LOG_DEBUG, + _alpm_log(db->handle, PM_LOG_DEBUG, "failed to load package cache for repository '%s'\n", db->treename); - return(-1); + return -1; } db->pkgcache_loaded = 1; - return(0); + return 0; } void _alpm_db_free_pkgcache(pmdb_t *db) { - ALPM_LOG_FUNC; - if(db == NULL || !db->pkgcache_loaded) { return; } - _alpm_log(PM_LOG_DEBUG, "freeing package cache for repository '%s'\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "freeing package cache for repository '%s'\n", db->treename); alpm_list_free_inner(_alpm_db_get_pkgcache(db), @@ -493,10 +513,8 @@ void _alpm_db_free_pkgcache(pmdb_t *db) pmpkghash_t *_alpm_db_get_pkgcache_hash(pmdb_t *db) { - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } if(!db->pkgcache_loaded) { @@ -505,23 +523,21 @@ pmpkghash_t *_alpm_db_get_pkgcache_hash(pmdb_t *db) /* hmmm, still NULL ?*/ if(!db->pkgcache) { - _alpm_log(PM_LOG_DEBUG, "warning: pkgcache is NULL for db '%s'\n", db->treename); + _alpm_log(db->handle, PM_LOG_DEBUG, "warning: pkgcache is NULL for db '%s'\n", db->treename); } - return(db->pkgcache); + return db->pkgcache; } alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db) { - ALPM_LOG_FUNC; - pmpkghash_t *hash = _alpm_db_get_pkgcache_hash(db); if(hash == NULL) { - return(NULL); + return NULL; } - return(hash->list); + return hash->list; } /* "duplicate" pkg then add it to pkgcache */ @@ -529,70 +545,64 @@ int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg) { pmpkg_t *newpkg; - ALPM_LOG_FUNC; - if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { - return(-1); + return -1; } newpkg = _alpm_pkg_dup(pkg); if(newpkg == NULL) { - return(-1); + return -1; } - _alpm_log(PM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n", alpm_pkg_get_name(newpkg), db->treename); db->pkgcache = _alpm_pkghash_add_sorted(db->pkgcache, newpkg); _alpm_db_free_grpcache(db); - return(0); + return 0; } int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg) { pmpkg_t *data = NULL; - ALPM_LOG_FUNC; - if(db == NULL || !db->pkgcache_loaded || pkg == NULL) { - return(-1); + return -1; } - _alpm_log(PM_LOG_DEBUG, "removing entry '%s' from '%s' cache\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "removing entry '%s' from '%s' cache\n", alpm_pkg_get_name(pkg), db->treename); db->pkgcache = _alpm_pkghash_remove(db->pkgcache, pkg, &data); if(data == NULL) { /* package not found */ - _alpm_log(PM_LOG_DEBUG, "cannot remove entry '%s' from '%s' cache: not found\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "cannot remove entry '%s' from '%s' cache: not found\n", alpm_pkg_get_name(pkg), db->treename); - return(-1); + return -1; } _alpm_pkg_free(data); _alpm_db_free_grpcache(db); - return(0); + return 0; } pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target) { - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } pmpkghash_t *pkgcache = _alpm_db_get_pkgcache_hash(db); if(!pkgcache) { - _alpm_log(PM_LOG_DEBUG, "warning: failed to get '%s' from NULL pkgcache\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "warning: failed to get '%s' from NULL pkgcache\n", target); - return(NULL); + return NULL; } - return(_alpm_pkghash_find(pkgcache, target)); + return _alpm_pkghash_find(pkgcache, target); } /* Returns a new group cache from db. @@ -601,13 +611,11 @@ int _alpm_db_load_grpcache(pmdb_t *db) { alpm_list_t *lp; - ALPM_LOG_FUNC; - if(db == NULL) { - return(-1); + return -1; } - _alpm_log(PM_LOG_DEBUG, "loading group cache for repository '%s'\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "loading group cache for repository '%s'\n", db->treename); for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { @@ -636,26 +644,28 @@ int _alpm_db_load_grpcache(pmdb_t *db) } /* we didn't find the group, so create a new one with this name */ grp = _alpm_grp_new(grpname); + if(!grp) { + _alpm_db_free_grpcache(db); + return -1; + } grp->packages = alpm_list_add(grp->packages, pkg); db->grpcache = alpm_list_add(db->grpcache, grp); } } db->grpcache_loaded = 1; - return(0); + return 0; } void _alpm_db_free_grpcache(pmdb_t *db) { alpm_list_t *lg; - ALPM_LOG_FUNC; - if(db == NULL || !db->grpcache_loaded) { return; } - _alpm_log(PM_LOG_DEBUG, "freeing group cache for repository '%s'\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "freeing group cache for repository '%s'\n", db->treename); for(lg = db->grpcache; lg; lg = lg->next) { @@ -668,38 +678,34 @@ void _alpm_db_free_grpcache(pmdb_t *db) alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db) { - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } if(!db->grpcache_loaded) { _alpm_db_load_grpcache(db); } - return(db->grpcache); + return db->grpcache; } pmgrp_t *_alpm_db_get_grpfromcache(pmdb_t *db, const char *target) { alpm_list_t *i; - ALPM_LOG_FUNC; - if(db == NULL || target == NULL || strlen(target) == 0) { - return(NULL); + return NULL; } for(i = _alpm_db_get_grpcache(db); i; i = i->next) { pmgrp_t *info = i->data; if(strcmp(info->name, target) == 0) { - return(info); + return info; } } - return(NULL); + return NULL; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 75776d71..e3faeeb4 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -22,15 +22,16 @@ #ifndef _ALPM_DB_H #define _ALPM_DB_H -#include "alpm.h" -#include "pkghash.h" - #include <time.h> /* libarchive */ #include <archive.h> #include <archive_entry.h> +#include "alpm.h" +#include "pkghash.h" +#include "signing.h" + /* Database entries */ typedef enum _pmdbinfrq_t { INFRQ_BASE = 1, @@ -50,6 +51,7 @@ struct db_operations { /* Database */ struct __pmdb_t { + pmhandle_t *handle; char *treename; /* do not access directly, use _alpm_db_path(db) for lazy access */ char *_path; @@ -60,6 +62,7 @@ struct __pmdb_t { pmpkghash_t *pkgcache; alpm_list_t *grpcache; alpm_list_t *servers; + pgp_verify_t pgp_verify; struct db_operations *ops; }; @@ -69,11 +72,12 @@ struct __pmdb_t { pmdb_t *_alpm_db_new(const char *treename, int is_local); void _alpm_db_free(pmdb_t *db); const char *_alpm_db_path(pmdb_t *db); +char *_alpm_db_sig_path(pmdb_t *db); int _alpm_db_version(pmdb_t *db); int _alpm_db_cmp(const void *d1, const void *d2); alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles); -pmdb_t *_alpm_db_register_local(void); -pmdb_t *_alpm_db_register_sync(const char *treename); +pmdb_t *_alpm_db_register_local(pmhandle_t *handle); +pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename); void _alpm_db_unregister(pmdb_t *db); /* be_*.c, backend specific calls */ diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c index 10c982f2..aa76b492 100644 --- a/lib/libalpm/delta.c +++ b/lib/libalpm/delta.c @@ -41,32 +41,32 @@ const char SYMEXPORT *alpm_delta_get_from(pmdelta_t *delta) { - ASSERT(delta != NULL, return(NULL)); - return(delta->from); + ASSERT(delta != NULL, return NULL); + return delta->from; } const char SYMEXPORT *alpm_delta_get_to(pmdelta_t *delta) { - ASSERT(delta != NULL, return(NULL)); - return(delta->to); + ASSERT(delta != NULL, return NULL); + return delta->to; } const char SYMEXPORT *alpm_delta_get_filename(pmdelta_t *delta) { - ASSERT(delta != NULL, return(NULL)); - return(delta->delta); + ASSERT(delta != NULL, return NULL); + return delta->delta; } const char SYMEXPORT *alpm_delta_get_md5sum(pmdelta_t *delta) { - ASSERT(delta != NULL, return(NULL)); - return(delta->delta_md5); + ASSERT(delta != NULL, return NULL); + return delta->delta_md5; } off_t SYMEXPORT alpm_delta_get_size(pmdelta_t *delta) { - ASSERT(delta != NULL, return(-1)); - return(delta->delta_size); + ASSERT(delta != NULL, return -1); + return delta->delta_size; } /** @} */ @@ -78,6 +78,10 @@ static alpm_list_t *graph_init(alpm_list_t *deltas, int reverse) /* create the vertices */ for(i = deltas; i; i = i->next) { pmgraph_t *v = _alpm_graph_new(); + if(!v) { + alpm_list_free(vertices); + return NULL; + } pmdelta_t *vdelta = i->data; vdelta->download_size = vdelta->delta_size; v->weight = LONG_MAX; @@ -108,10 +112,10 @@ static alpm_list_t *graph_init(alpm_list_t *deltas, int reverse) } v_i->childptr = v_i->children; } - return(vertices); + return vertices; } -static void graph_init_size(alpm_list_t *vertices) +static void graph_init_size(pmhandle_t *handle, alpm_list_t *vertices) { alpm_list_t *i; @@ -121,7 +125,7 @@ static void graph_init_size(alpm_list_t *vertices) pmdelta_t *vdelta = v->data; /* determine whether the delta file already exists */ - fpath = _alpm_filecache_find(vdelta->delta); + fpath = _alpm_filecache_find(handle, vdelta->delta); md5sum = alpm_compute_md5sum(fpath); if(fpath && md5sum && strcmp(md5sum, vdelta->delta_md5) == 0) { vdelta->download_size = 0; @@ -130,7 +134,7 @@ static void graph_init_size(alpm_list_t *vertices) FREE(md5sum); /* determine whether a base 'from' file exists */ - fpath = _alpm_filecache_find(vdelta->from); + fpath = _alpm_filecache_find(handle, vdelta->from); if(fpath) { v->weight = vdelta->download_size; } @@ -205,12 +209,13 @@ static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t ** *path = alpm_list_reverse(rpath); alpm_list_free(rpath); - return(bestsize); + return bestsize; } /** Calculates the shortest path from one version to another. * The shortest path is defined as the path with the smallest combined * size, not the length of the path. + * @param handle the context handle * @param deltas the list of pmdelta_t * objects that a file has * @param to the file to start the search at * @param path the pointer to a list location where pmdelta_t * objects that @@ -218,34 +223,32 @@ static off_t shortest_path(alpm_list_t *vertices, const char *to, alpm_list_t ** * possible with the files available. * @return the size of the path stored, or LONG_MAX if path is unfindable */ -off_t _alpm_shortest_delta_path(alpm_list_t *deltas, +off_t _alpm_shortest_delta_path(pmhandle_t *handle, alpm_list_t *deltas, const char *to, alpm_list_t **path) { alpm_list_t *bestpath = NULL; alpm_list_t *vertices; off_t bestsize = LONG_MAX; - ALPM_LOG_FUNC; - if(deltas == NULL) { *path = NULL; - return(bestsize); + return bestsize; } - _alpm_log(PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to); + _alpm_log(handle, PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to); vertices = graph_init(deltas, 0); - graph_init_size(vertices); + graph_init_size(handle, vertices); dijkstra(vertices); bestsize = shortest_path(vertices, to, &bestpath); - _alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize); + _alpm_log(handle, PM_LOG_DEBUG, "delta shortest-path search complete : '%jd'\n", (intmax_t)bestsize); alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); *path = bestpath; - return(bestsize); + return bestsize; } static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota) @@ -273,7 +276,7 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota } alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); - return(unused); + return unused; } alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(pmpkg_t *pkg) @@ -283,7 +286,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(pmpkg_t *pkg) alpm_pkg_get_deltas(pkg), alpm_pkg_get_filename(pkg), pkgsize * MAX_DELTA_RATIO); - return(unused); + return unused; } @@ -308,21 +311,21 @@ pmdelta_t *_alpm_delta_parse(char *line) if(regexec(®, line, 0, 0, 0) != 0) { /* delta line is invalid, return NULL */ regfree(®); - return(NULL); + return NULL; } regfree(®); - CALLOC(delta, 1, sizeof(pmdelta_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(delta, 1, sizeof(pmdelta_t), return NULL); tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - STRDUP(delta->delta, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(delta->delta, tmp2, return NULL); tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - STRDUP(delta->delta_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(delta->delta_md5, tmp2, return NULL); tmp2 = tmp; tmp = strchr(tmp, ' '); @@ -332,14 +335,12 @@ pmdelta_t *_alpm_delta_parse(char *line) tmp2 = tmp; tmp = strchr(tmp, ' '); *(tmp++) = '\0'; - STRDUP(delta->from, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(delta->from, tmp2, return NULL); tmp2 = tmp; - STRDUP(delta->to, tmp2, RET_ERR(PM_ERR_MEMORY, NULL)); - - _alpm_log(PM_LOG_DEBUG, "delta : %s %s '%jd'\n", delta->from, delta->to, (intmax_t)delta->delta_size); + STRDUP(delta->to, tmp2, return NULL); - return(delta); + return delta; } void _alpm_delta_free(pmdelta_t *delta) diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h index d7a81c47..d7725f5a 100644 --- a/lib/libalpm/delta.h +++ b/lib/libalpm/delta.h @@ -20,6 +20,8 @@ #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" @@ -29,19 +31,19 @@ struct __pmdelta_t { char *delta; /** md5sum of the delta file */ char *delta_md5; - /** filesize of the delta file */ - off_t delta_size; /** filename of the 'before' file */ char *from; /** filename of the 'after' file */ char *to; + /** filesize of the delta file */ + off_t delta_size; /** download filesize of the delta file */ off_t download_size; }; pmdelta_t *_alpm_delta_parse(char *line); void _alpm_delta_free(pmdelta_t *delta); -off_t _alpm_shortest_delta_path(alpm_list_t *deltas, +off_t _alpm_shortest_delta_path(pmhandle_t *handle, alpm_list_t *deltas, const char *to, alpm_list_t **path); /* max percent of package size to download deltas */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 36d6e1aa..10c0009d 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -35,6 +35,7 @@ #include "package.h" #include "db.h" #include "handle.h" +#include "trans.h" void _alpm_dep_free(pmdepend_t *dep) { @@ -48,15 +49,13 @@ static pmdepmissing_t *depmiss_new(const char *target, pmdepend_t *dep, { pmdepmissing_t *miss; - ALPM_LOG_FUNC; + MALLOC(miss, sizeof(pmdepmissing_t), return NULL); - MALLOC(miss, sizeof(pmdepmissing_t), RET_ERR(PM_ERR_MEMORY, NULL)); - - STRDUP(miss->target, target, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(miss->target, target, return NULL); miss->depend = _alpm_dep_dup(dep); - STRDUP(miss->causingpkg, causingpkg, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(miss->causingpkg, causingpkg, return NULL); - return(miss); + return miss; } void _alpm_depmiss_free(pmdepmissing_t *miss) @@ -73,10 +72,10 @@ static int _alpm_dep_edge(pmpkg_t *pkg1, pmpkg_t *pkg2) alpm_list_t *i; for(i = alpm_pkg_get_depends(pkg1); i; i = i->next) { if(_alpm_depcmp(pkg2, i->data)) { - return(1); + return 1; } } - return(0); + return 0; } /* Convert a list of pmpkg_t * to a graph structure, @@ -110,7 +109,7 @@ static alpm_list_t *dep_graph_init(alpm_list_t *targets) } vertex_i->childptr = vertex_i->children; } - return(vertices); + return vertices; } /* Re-order a list of target packages with respect to their dependencies. @@ -127,20 +126,19 @@ static alpm_list_t *dep_graph_init(alpm_list_t *targets) * This function returns the new alpm_list_t* target list. * */ -alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) +alpm_list_t *_alpm_sortbydeps(pmhandle_t *handle, + alpm_list_t *targets, int reverse) { alpm_list_t *newtargs = NULL; alpm_list_t *vertices = NULL; alpm_list_t *vptr; pmgraph_t *vertex; - ALPM_LOG_FUNC; - if(targets == NULL) { - return(NULL); + return NULL; } - _alpm_log(PM_LOG_DEBUG, "started sorting dependencies\n"); + _alpm_log(handle, PM_LOG_DEBUG, "started sorting dependencies\n"); vertices = dep_graph_init(targets); @@ -153,7 +151,7 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) while(vertex->childptr && !found) { pmgraph_t *nextchild = vertex->childptr->data; vertex->childptr = vertex->childptr->next; - if (nextchild->state == 0) { + if(nextchild->state == 0) { found = 1; nextchild->parent = vertex; vertex = nextchild; @@ -163,13 +161,13 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) pmpkg_t *childpkg = nextchild->data; const char *message; - _alpm_log(PM_LOG_WARNING, _("dependency cycle detected:\n")); + _alpm_log(handle, PM_LOG_WARNING, _("dependency cycle detected:\n")); if(reverse) { message =_("%s will be removed after its %s dependency\n"); } else { message =_("%s will be installed before its %s dependency\n"); } - _alpm_log(PM_LOG_WARNING, message, vertexpkg->name, childpkg->name); + _alpm_log(handle, PM_LOG_WARNING, message, vertexpkg->name, childpkg->name); } } if(!found) { @@ -181,14 +179,14 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) vptr = vptr->next; while(vptr) { vertex = vptr->data; - if (vertex->state == 0) break; + if(vertex->state == 0) break; vptr = vptr->next; } } } } - _alpm_log(PM_LOG_DEBUG, "sorting dependencies finished\n"); + _alpm_log(handle, PM_LOG_DEBUG, "sorting dependencies finished\n"); if(reverse) { /* reverse the order */ @@ -201,12 +199,12 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse) alpm_list_free_inner(vertices, _alpm_graph_free); alpm_list_free(vertices); - return(newtargs); + return newtargs; } -static int no_dep_version(void) +static int no_dep_version(pmhandle_t *handle) { - int flags = alpm_trans_get_flags(); + int flags = alpm_trans_get_flags(handle); return flags != -1 && (flags & PM_TRANS_FLAG_NODEPVERSION); } @@ -214,7 +212,7 @@ static pmdepend_t *filtered_depend(pmdepend_t *dep, int nodepversion) { if(nodepversion) { pmdepend_t *newdep = _alpm_dep_dup(dep); - ASSERT(newdep, return(dep)); + ASSERT(newdep, return dep); newdep->mod = PM_DEP_MOD_ANY; dep = newdep; } @@ -235,10 +233,10 @@ static pmpkg_t *find_dep_satisfier(alpm_list_t *pkgs, pmdepend_t *dep) for(i = pkgs; i; i = alpm_list_next(i)) { pmpkg_t *pkg = i->data; if(_alpm_depcmp(pkg, dep)) { - return(pkg); + return pkg; } } - return(NULL); + return NULL; } /** Find a package satisfying a specified dependency. @@ -250,28 +248,32 @@ static pmpkg_t *find_dep_satisfier(alpm_list_t *pkgs, pmdepend_t *dep) pmpkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring) { pmdepend_t *dep = _alpm_splitdep(depstring); + if(!dep) { + return NULL; + } pmpkg_t *pkg = find_dep_satisfier(pkgs, dep); _alpm_dep_free(dep); - return(pkg); + return pkg; } /** Checks dependencies and returns missing ones in a list. * Dependencies can include versions with depmod operators. + * @param handle the context handle * @param pkglist the list of local packages - * @param reversedeps handles the backward dependencies * @param remove an alpm_list_t* of packages to be removed * @param upgrade an alpm_list_t* of packages to be upgraded (remove-then-upgrade) + * @param reversedeps handles the backward dependencies * @return an alpm_list_t* of pmdepmissing_t pointers. */ -alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, - alpm_list_t *remove, alpm_list_t *upgrade) +alpm_list_t SYMEXPORT *alpm_checkdeps(pmhandle_t *handle, alpm_list_t *pkglist, + alpm_list_t *remove, alpm_list_t *upgrade, int reversedeps) { alpm_list_t *i, *j; alpm_list_t *targets, *dblist = NULL, *modified = NULL; alpm_list_t *baddeps = NULL; int nodepversion; - ALPM_LOG_FUNC; + CHECK_HANDLE(handle, return NULL); targets = alpm_list_join(alpm_list_copy(remove), alpm_list_copy(upgrade)); for(i = pkglist; i; i = i->next) { @@ -284,12 +286,12 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, } alpm_list_free(targets); - nodepversion = no_dep_version(); + nodepversion = no_dep_version(handle); /* look for unsatisfied dependencies of the upgrade list */ for(i = upgrade; i; i = i->next) { pmpkg_t *tp = i->data; - _alpm_log(PM_LOG_DEBUG, "checkdeps: package %s-%s\n", + _alpm_log(handle, PM_LOG_DEBUG, "checkdeps: package %s-%s\n", alpm_pkg_get_name(tp), alpm_pkg_get_version(tp)); for(j = alpm_pkg_get_depends(tp); j; j = j->next) { @@ -302,7 +304,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, /* Unsatisfied dependency in the upgrade list */ pmdepmissing_t *miss; char *missdepstring = alpm_dep_compute_string(depend); - _alpm_log(PM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n", + _alpm_log(handle, PM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n", missdepstring, alpm_pkg_get_name(tp)); free(missdepstring); miss = depmiss_new(alpm_pkg_get_name(tp), depend, NULL); @@ -329,7 +331,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, !find_dep_satisfier(dblist, depend)) { pmdepmissing_t *miss; char *missdepstring = alpm_dep_compute_string(depend); - _alpm_log(PM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n", + _alpm_log(handle, PM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n", missdepstring, alpm_pkg_get_name(lp)); free(missdepstring); miss = depmiss_new(lp->name, depend, alpm_pkg_get_name(causingpkg)); @@ -343,7 +345,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, alpm_list_free(modified); alpm_list_free(dblist); - return(baddeps); + return baddeps; } static int dep_vercmp(const char *version1, pmdepmod_t mod, @@ -364,7 +366,7 @@ static int dep_vercmp(const char *version1, pmdepmod_t mod, default: equal = 1; break; } } - return(equal); + return equal; } int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) @@ -380,7 +382,7 @@ int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) satisfy = (strcmp(pkg->name, dep->name) == 0 && dep_vercmp(pkg->version, dep->mod, dep->version)); if(satisfy) { - return(satisfy); + return satisfy; } } @@ -406,7 +408,7 @@ int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) } } - return(satisfy); + return satisfy; } pmdepend_t *_alpm_splitdep(const char *depstring) @@ -415,10 +417,10 @@ pmdepend_t *_alpm_splitdep(const char *depstring) const char *ptr, *version = NULL; if(depstring == NULL) { - return(NULL); + return NULL; } - CALLOC(depend, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(depend, 1, sizeof(pmdepend_t), return NULL); /* Find a version comparator if one exists. If it does, set the type and * increment the ptr accordingly so we can copy the right strings. */ @@ -444,27 +446,26 @@ pmdepend_t *_alpm_splitdep(const char *depstring) } /* copy the right parts to the right places */ - STRNDUP(depend->name, depstring, ptr - depstring, - RET_ERR(PM_ERR_MEMORY, NULL)); + STRNDUP(depend->name, depstring, ptr - depstring, return NULL); depend->name_hash = _alpm_hash_sdbm(depend->name); if(version) { - STRDUP(depend->version, version, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(depend->version, version, return NULL); } - return(depend); + return depend; } pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep) { pmdepend_t *newdep; - CALLOC(newdep, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(newdep, 1, sizeof(pmdepend_t), return NULL); - STRDUP(newdep->name, dep->name, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newdep->name, dep->name, return NULL); newdep->name_hash = dep->name_hash; - STRDUP(newdep->version, dep->version, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newdep->version, dep->version, return NULL); newdep->mod = dep->mod; - return(newdep); + return newdep; } /* These parameters are messy. We check if this package, given a list of @@ -477,15 +478,15 @@ static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets, alpm_list_t *i; if(_alpm_pkg_find(targets, alpm_pkg_get_name(pkg))) { - return(0); + return 0; } if(!include_explicit) { /* see if it was explicitly installed */ if(alpm_pkg_get_reason(pkg) == PM_PKG_REASON_EXPLICIT) { - _alpm_log(PM_LOG_DEBUG, "excluding %s -- explicitly installed\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "excluding %s -- explicitly installed\n", alpm_pkg_get_name(pkg)); - return(0); + return 0; } } @@ -499,12 +500,12 @@ static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets, for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { pmpkg_t *lpkg = i->data; if(_alpm_dep_edge(lpkg, pkg) && !_alpm_pkg_find(targets, lpkg->name)) { - return(0); + return 0; } } /* it's ok to remove */ - return(1); + return 1; } /** @@ -521,8 +522,6 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) { alpm_list_t *i, *j; - ALPM_LOG_FUNC; - if(db == NULL || targs == NULL) { return; } @@ -533,7 +532,7 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) pmpkg_t *deppkg = j->data; if(_alpm_dep_edge(pkg, deppkg) && can_remove_package(db, deppkg, targs, include_explicit)) { - _alpm_log(PM_LOG_DEBUG, "adding '%s' to the targets\n", + _alpm_log(db->handle, PM_LOG_DEBUG, "adding '%s' to the targets\n", alpm_pkg_get_name(deppkg)); /* add it to the target list */ targs = alpm_list_add(targs, _alpm_pkg_dup(deppkg)); @@ -545,6 +544,7 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) /** * helper function for resolvedeps: search for dep satisfier in dbs * + * @param handle the context handle * @param dep is the dependency to search for * @param dbs are the databases to search * @param excluding are the packages to exclude from the search @@ -554,8 +554,8 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) * an error code without prompting * @return the resolved package **/ -static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, - alpm_list_t *excluding, int prompt) +static pmpkg_t *resolvedep(pmhandle_t *handle, pmdepend_t *dep, + alpm_list_t *dbs, alpm_list_t *excluding, int prompt) { alpm_list_t *i, *j; int ignored = 0; @@ -567,20 +567,20 @@ static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, for(i = dbs; i; i = i->next) { pmpkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); if(pkg && _alpm_depcmp(pkg, dep) && !_alpm_pkg_find(excluding, pkg->name)) { - if(_alpm_pkg_should_ignore(pkg)) { + if(_alpm_pkg_should_ignore(handle, pkg)) { int install = 0; - if (prompt) { + if(prompt) { QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); } else { - _alpm_log(PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); + _alpm_log(handle, PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); } if(!install) { ignored = 1; continue; } } - return(pkg); + return pkg; } } /* 2. satisfiers (skip literals here) */ @@ -589,20 +589,20 @@ static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, pmpkg_t *pkg = j->data; if(_alpm_depcmp(pkg, dep) && strcmp(pkg->name, dep->name) != 0 && !_alpm_pkg_find(excluding, pkg->name)) { - if(_alpm_pkg_should_ignore(pkg)) { + if(_alpm_pkg_should_ignore(handle, pkg)) { int install = 0; - if (prompt) { + if(prompt) { QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); } else { - _alpm_log(PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); + _alpm_log(handle, PM_LOG_WARNING, _("ignoring package %s-%s\n"), pkg->name, pkg->version); } if(!install) { ignored = 1; continue; } } - _alpm_log(PM_LOG_DEBUG, "provider found (%s provides %s)\n", + _alpm_log(handle, PM_LOG_DEBUG, "provider found (%s provides %s)\n", pkg->name, dep->name); providers = alpm_list_add(providers, pkg); /* keep looking for other providers in the all dbs */ @@ -613,13 +613,13 @@ static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, /* first check if one provider is already installed locally */ for(i = providers; i; i = i->next) { pmpkg_t *pkg = i->data; - if (_alpm_pkghash_find(_alpm_db_get_pkgcache_hash(handle->db_local), pkg->name)) { + if(_alpm_pkghash_find(_alpm_db_get_pkgcache_hash(handle->db_local), pkg->name)) { alpm_list_free(providers); - return(pkg); + return pkg; } } count = alpm_list_count(providers); - if (count >= 1) { + if(count >= 1) { /* default to first provider if there is no QUESTION callback */ int index = 0; if(count > 1) { @@ -630,48 +630,51 @@ static pmpkg_t *resolvedep(pmdepend_t *dep, alpm_list_t *dbs, if(index >= 0 && index < count) { pmpkg_t *pkg = alpm_list_getdata(alpm_list_nth(providers, index)); alpm_list_free(providers); - return(pkg); + return pkg; } alpm_list_free(providers); providers = NULL; } if(ignored) { /* resolvedeps will override these */ - pm_errno = PM_ERR_PKG_IGNORED; + handle->pm_errno = PM_ERR_PKG_IGNORED; } else { - pm_errno = PM_ERR_PKG_NOT_FOUND; + handle->pm_errno = PM_ERR_PKG_NOT_FOUND; } - return(NULL); + return NULL; } /** Find a package satisfying a specified dependency. * First look for a literal, going through each db one by one. Then look for * providers. The first satisfier found is returned. * The dependency can include versions with depmod operators. + * @param handle the context handle * @param dbs an alpm_list_t* of pmdb_t where the satisfier will be searched * @param depstring package or provision name, versioned or not * @return a pmpkg_t* satisfying depstring */ -pmpkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_list_t *dbs, const char *depstring) +pmpkg_t SYMEXPORT *alpm_find_dbs_satisfier(pmhandle_t *handle, + alpm_list_t *dbs, const char *depstring) { pmdepend_t *dep; pmpkg_t *pkg; - ASSERT(dbs, return(NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(dbs, RET_ERR(handle, PM_ERR_WRONG_ARGS, NULL)); dep = _alpm_splitdep(depstring); - ASSERT(dep, return(NULL)); - pkg = resolvedep(dep, dbs, NULL, 1); + ASSERT(dep, return NULL); + pkg = resolvedep(handle, dep, dbs, NULL, 1); _alpm_dep_free(dep); - return(pkg); + return pkg; } /** * Computes resolvable dependencies for a given package and adds that package * and those resolvable dependencies to a list. * + * @param handle the context handle * @param localpkgs is the list of local packages - * @param dbs_sync are the sync databases * @param pkg is the package to resolve * @param packages is a pointer to a list of packages which will be * searched first for any dependency packages needed to complete the @@ -686,7 +689,7 @@ pmpkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_list_t *dbs, const char *depstri * unresolvable dependency, in which case the [*packages] list will be * unmodified by this function */ -int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pkg, +int _alpm_resolvedeps(pmhandle_t *handle, alpm_list_t *localpkgs, pmpkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_list_t **data) { @@ -696,10 +699,8 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk alpm_list_t *deps = NULL; alpm_list_t *packages_copy; - ALPM_LOG_FUNC; - if(_alpm_pkg_find(*packages, pkg->name) != NULL) { - return(0); + return 0; } /* Create a copy of the packages list, so that it can be restored @@ -709,11 +710,11 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk on that list */ *packages = alpm_list_add(*packages, pkg); - _alpm_log(PM_LOG_DEBUG, "started resolving dependencies\n"); + _alpm_log(handle, PM_LOG_DEBUG, "started resolving dependencies\n"); for(i = alpm_list_last(*packages); i; i = i->next) { pmpkg_t *tpkg = i->data; targ = alpm_list_add(NULL, tpkg); - deps = alpm_checkdeps(localpkgs, 0, remove, targ); + deps = alpm_checkdeps(handle, localpkgs, remove, targ, 0); alpm_list_free(targ); for(j = deps; j; j = j->next) { @@ -730,12 +731,12 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk pmpkg_t *spkg = find_dep_satisfier(preferred, missdep); if(!spkg) { /* find a satisfier package in the given repositories */ - spkg = resolvedep(missdep, dbs_sync, *packages, 0); + spkg = resolvedep(handle, missdep, handle->dbs_sync, *packages, 0); } if(!spkg) { - pm_errno = PM_ERR_UNSATISFIED_DEPS; + handle->pm_errno = PM_ERR_UNSATISFIED_DEPS; char *missdepstring = alpm_dep_compute_string(missdep); - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, PM_LOG_WARNING, _("cannot resolve \"%s\", a dependency of \"%s\"\n"), missdepstring, tpkg->name); free(missdepstring); @@ -744,7 +745,7 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk } ret = -1; } else { - _alpm_log(PM_LOG_DEBUG, "pulling dependency %s (needed by %s)\n", + _alpm_log(handle, PM_LOG_DEBUG, "pulling dependency %s (needed by %s)\n", alpm_pkg_get_name(spkg), alpm_pkg_get_name(tpkg)); *packages = alpm_list_add(*packages, spkg); _alpm_depmiss_free(miss); @@ -759,68 +760,44 @@ int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pk } else { alpm_list_free(packages_copy); } - _alpm_log(PM_LOG_DEBUG, "finished resolving dependencies\n"); - return(ret); + _alpm_log(handle, PM_LOG_DEBUG, "finished resolving dependencies\n"); + return ret; } const char SYMEXPORT *alpm_miss_get_target(const pmdepmissing_t *miss) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(miss != NULL, return(NULL)); - - return(miss->target); + ASSERT(miss != NULL, return NULL); + return miss->target; } const char SYMEXPORT *alpm_miss_get_causingpkg(const pmdepmissing_t *miss) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(miss != NULL, return(NULL)); - + ASSERT(miss != NULL, return NULL); return miss->causingpkg; } pmdepend_t SYMEXPORT *alpm_miss_get_dep(pmdepmissing_t *miss) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(miss != NULL, return(NULL)); - - return(miss->depend); + ASSERT(miss != NULL, return NULL); + return miss->depend; } pmdepmod_t SYMEXPORT alpm_dep_get_mod(const pmdepend_t *dep) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(-1)); - - return(dep->mod); + ASSERT(dep != NULL, return -1); + return dep->mod; } const char SYMEXPORT *alpm_dep_get_name(const pmdepend_t *dep) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(NULL)); - - return(dep->name); + ASSERT(dep != NULL, return NULL); + return dep->name; } const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(NULL)); - - return(dep->version); + ASSERT(dep != NULL, return NULL); + return dep->version; } /** Reverse of splitdep; make a dep string from a pmdepend_t struct. @@ -834,10 +811,7 @@ char SYMEXPORT *alpm_dep_compute_string(const pmdepend_t *dep) char *str; size_t len; - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(dep != NULL, return(NULL)); + ASSERT(dep != NULL, return NULL); if(dep->name) { name = dep->name; @@ -879,9 +853,9 @@ char SYMEXPORT *alpm_dep_compute_string(const pmdepend_t *dep) * and ver will be empty when PM_DEP_MOD_ANY is the depend type. the * reassignments above also ensure we do not do a strlen(NULL). */ len = strlen(name) + strlen(opr) + strlen(ver) + 1; - MALLOC(str, len, RET_ERR(PM_ERR_MEMORY, NULL)); + MALLOC(str, len, return NULL); snprintf(str, len, "%s%s%s", name, opr, ver); - return(str); + return str; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index f728cad0..97c0918e 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -45,9 +45,9 @@ struct __pmdepmissing_t { void _alpm_dep_free(pmdepend_t *dep); pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep); void _alpm_depmiss_free(pmdepmissing_t *miss); -alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, int reverse); +alpm_list_t *_alpm_sortbydeps(pmhandle_t *handle, alpm_list_t *targets, int reverse); void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit); -int _alpm_resolvedeps(alpm_list_t *localpkgs, alpm_list_t *dbs_sync, pmpkg_t *pkg, +int _alpm_resolvedeps(pmhandle_t *handle, alpm_list_t *localpkgs, pmpkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_list_t **data); pmdepend_t *_alpm_splitdep(const char *depstring); diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 066107d7..079e683e 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -56,10 +56,10 @@ static int mount_point_cmp(const void *p1, const void *p2) const alpm_mountpoint_t *mp1 = p1; const alpm_mountpoint_t *mp2 = p2; /* the negation will sort all mountpoints before their parent */ - return(-strcmp(mp1->mount_dir, mp2->mount_dir)); + return -strcmp(mp1->mount_dir, mp2->mount_dir); } -static alpm_list_t *mount_point_list(void) +static alpm_list_t *mount_point_list(pmhandle_t *handle) { alpm_list_t *mount_points = NULL, *ptr; alpm_mountpoint_t *mp; @@ -71,23 +71,23 @@ static alpm_list_t *mount_point_list(void) fp = setmntent(MOUNTED, "r"); - if (fp == NULL) { - return(NULL); + if(fp == NULL) { + return NULL; } while((mnt = getmntent(fp))) { if(!mnt) { - _alpm_log(PM_LOG_WARNING, _("could not get filesystem information\n")); + _alpm_log(handle, PM_LOG_WARNING, _("could not get filesystem information\n")); continue; } if(statvfs(mnt->mnt_dir, &fsp) != 0) { - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, PM_LOG_WARNING, _("could not get filesystem information for %s: %s\n"), mnt->mnt_dir, strerror(errno)); continue; } - CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, PM_ERR_MEMORY, NULL)); mp->mount_dir = strdup(mnt->mnt_dir); mp->mount_dir_len = strlen(mp->mount_dir); memcpy(&(mp->fsp), &fsp, sizeof(struct statvfs)); @@ -103,8 +103,8 @@ static alpm_list_t *mount_point_list(void) entries = getmntinfo(&fsp, MNT_NOWAIT); - if (entries < 0) { - return(NULL); + if(entries < 0) { + return NULL; } for(; entries-- > 0; fsp++) { @@ -126,9 +126,9 @@ static alpm_list_t *mount_point_list(void) mount_point_cmp); for(ptr = mount_points; ptr != NULL; ptr = ptr->next) { mp = ptr->data; - _alpm_log(PM_LOG_DEBUG, "mountpoint: %s\n", mp->mount_dir); + _alpm_log(handle, PM_LOG_DEBUG, "mountpoint: %s\n", mp->mount_dir); } - return(mount_points); + return mount_points; } static alpm_mountpoint_t *match_mount_point(const alpm_list_t *mount_points, @@ -140,16 +140,16 @@ static alpm_mountpoint_t *match_mount_point(const alpm_list_t *mount_points, alpm_mountpoint_t *data = mp->data; if(strncmp(data->mount_dir, real_path, data->mount_dir_len) == 0) { - return(data); + return data; } } /* should not get here... */ - return(NULL); + return NULL; } -static int calculate_removed_size(const alpm_list_t *mount_points, - pmpkg_t *pkg) +static int calculate_removed_size(pmhandle_t *handle, + const alpm_list_t *mount_points, pmpkg_t *pkg) { alpm_list_t *file; @@ -171,7 +171,7 @@ static int calculate_removed_size(const alpm_list_t *mount_points, mp = match_mount_point(mount_points, path); if(mp == NULL) { - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, PM_LOG_WARNING, _("could not determine mount point for file %s\n"), filename); continue; } @@ -182,18 +182,18 @@ static int calculate_removed_size(const alpm_list_t *mount_points, mp->used |= USED_REMOVE; } - return(0); + return 0; } -static int calculate_installed_size(const alpm_list_t *mount_points, - pmpkg_t *pkg) +static int calculate_installed_size(pmhandle_t *handle, + const alpm_list_t *mount_points, pmpkg_t *pkg) { int ret=0; struct archive *archive; struct archive_entry *entry; - if ((archive = archive_read_new()) == NULL) { - pm_errno = PM_ERR_LIBARCHIVE; + if((archive = archive_read_new()) == NULL) { + handle->pm_errno = PM_ERR_LIBARCHIVE; ret = -1; goto cleanup; } @@ -203,7 +203,7 @@ static int calculate_installed_size(const alpm_list_t *mount_points, if(archive_read_open_filename(archive, pkg->origin_data.file, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - pm_errno = PM_ERR_PKG_OPEN; + handle->pm_errno = PM_ERR_PKG_OPEN; ret = -1; goto cleanup; } @@ -226,14 +226,14 @@ static int calculate_installed_size(const alpm_list_t *mount_points, /* approximate space requirements for db entries */ if(filename[0] == '.') { - filename = alpm_option_get_dbpath(); + filename = alpm_option_get_dbpath(handle); } snprintf(path, PATH_MAX, "%s%s", handle->root, filename); mp = match_mount_point(mount_points, path); if(mp == NULL) { - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, PM_LOG_WARNING, _("could not determine mount point for file %s\n"), filename); continue; } @@ -244,9 +244,9 @@ static int calculate_installed_size(const alpm_list_t *mount_points, mp->used |= USED_INSTALL; if(archive_read_data_skip(archive)) { - _alpm_log(PM_LOG_ERROR, _("error while reading package %s: %s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("error while reading package %s: %s\n"), pkg->name, archive_error_string(archive)); - pm_errno = PM_ERR_LIBARCHIVE; + handle->pm_errno = PM_ERR_LIBARCHIVE; break; } } @@ -254,28 +254,29 @@ static int calculate_installed_size(const alpm_list_t *mount_points, archive_read_finish(archive); cleanup: - return(ret); + return ret; } -int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) +int _alpm_check_diskspace(pmhandle_t *handle) { alpm_list_t *mount_points, *i; alpm_mountpoint_t *root_mp; size_t replaces = 0, current = 0, numtargs; int abort = 0; alpm_list_t *targ; + pmtrans_t *trans = handle->trans; numtargs = alpm_list_count(trans->add); - mount_points = mount_point_list(); + mount_points = mount_point_list(handle); if(mount_points == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not determine filesystem mount points\n")); - return(-1); + _alpm_log(handle, PM_LOG_ERROR, _("could not determine filesystem mount points\n")); + return -1; } root_mp = match_mount_point(mount_points, handle->root); if(root_mp == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not determine root mount point %s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not determine root mount point %s\n"), handle->root); - return(-1); + return -1; } replaces = alpm_list_count(trans->remove); @@ -288,7 +289,7 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) numtargs, current); local_pkg = targ->data; - calculate_removed_size(mount_points, local_pkg); + calculate_removed_size(handle, mount_points, local_pkg); } } @@ -300,11 +301,11 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) pkg = targ->data; /* is this package already installed? */ - local_pkg = _alpm_db_get_pkgfromcache(db_local, pkg->name); + local_pkg = _alpm_db_get_pkgfromcache(handle->db_local, pkg->name); if(local_pkg) { - calculate_removed_size(mount_points, local_pkg); + calculate_removed_size(handle, mount_points, local_pkg); } - calculate_installed_size(mount_points, pkg); + calculate_installed_size(handle, mount_points, pkg); for(i = mount_points; i; i = alpm_list_next(i)) { alpm_mountpoint_t *data = i->data; @@ -320,7 +321,7 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) for(i = mount_points; i; i = alpm_list_next(i)) { alpm_mountpoint_t *data = i->data; if(data->used && data->read_only) { - _alpm_log(PM_LOG_ERROR, _("Partition %s is mounted read only\n"), + _alpm_log(handle, PM_LOG_ERROR, _("Partition %s is mounted read only\n"), data->mount_dir); abort = 1; } else if(data->used & USED_INSTALL) { @@ -329,12 +330,12 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) long twentymb = (20 * 1024 * 1024 / (long)data->fsp.f_bsize) + 1; long cushion = fivepc < twentymb ? fivepc : twentymb; - _alpm_log(PM_LOG_DEBUG, "partition %s, needed %ld, cushion %ld, free %ld\n", + _alpm_log(handle, PM_LOG_DEBUG, "partition %s, needed %ld, cushion %ld, free %ld\n", data->mount_dir, data->max_blocks_needed, cushion, (unsigned long)data->fsp.f_bfree); if(data->max_blocks_needed + cushion >= 0 && (unsigned long)(data->max_blocks_needed + cushion) > data->fsp.f_bfree) { - _alpm_log(PM_LOG_ERROR, _("Partition %s too full: %ld blocks needed, %ld blocks free\n"), + _alpm_log(handle, PM_LOG_ERROR, _("Partition %s too full: %ld blocks needed, %ld blocks free\n"), data->mount_dir, data->max_blocks_needed + cushion, (unsigned long)data->fsp.f_bfree); abort = 1; @@ -349,10 +350,10 @@ int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local) FREELIST(mount_points); if(abort) { - RET_ERR(PM_ERR_DISK_SPACE, -1); + RET_ERR(handle, PM_ERR_DISK_SPACE, -1); } - return(0); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h index 2894a0c2..28aca7e9 100644 --- a/lib/libalpm/diskspace.h +++ b/lib/libalpm/diskspace.h @@ -46,7 +46,7 @@ typedef struct __alpm_mountpoint_t { FSSTATSTYPE fsp; } alpm_mountpoint_t; -int _alpm_check_diskspace(pmtrans_t *trans, pmdb_t *db_local); +int _alpm_check_diskspace(pmhandle_t *handle); #endif /* _ALPM_DISKSPACE_H */ diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index a98d84ac..93545624 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -29,14 +29,9 @@ #include <sys/types.h> #include <sys/stat.h> #include <signal.h> -/* the following two are needed for FreeBSD's libfetch */ -#include <limits.h> /* PATH_MAX */ -#if defined(HAVE_SYS_PARAM_H) -#include <sys/param.h> /* MAXHOSTNAMELEN */ -#endif -#ifdef HAVE_LIBFETCH -#include <fetch.h> +#ifdef HAVE_LIBCURL +#include <curl/curl.h> #endif /* libalpm */ @@ -47,112 +42,185 @@ #include "util.h" #include "handle.h" -static char *get_filename(const char *url) { +#ifdef HAVE_LIBCURL +static double prevprogress; /* last download amount */ +#endif + +static const char *get_filename(const char *url) +{ char *filename = strrchr(url, '/'); if(filename != NULL) { filename++; } - return(filename); + return filename; } -#ifdef HAVE_LIBFETCH -static char *get_destfile(const char *path, const char *filename) { - char *destfile; - /* len = localpath len + filename len + null */ - size_t len = strlen(path) + strlen(filename) + 1; - CALLOC(destfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); - snprintf(destfile, len, "%s%s", path, filename); +#ifdef HAVE_LIBCURL +static char *get_fullpath(const char *path, const char *filename, + const char *suffix) +{ + char *filepath; + /* len = localpath len + filename len + suffix len + null */ + size_t len = strlen(path) + strlen(filename) + strlen(suffix) + 1; + CALLOC(filepath, len, sizeof(char), return NULL); + snprintf(filepath, len, "%s%s%s", path, filename, suffix); - return(destfile); + return filepath; } -static char *get_tempfile(const char *path, const char *filename) { - char *tempfile; - /* len = localpath len + filename len + '.part' len + null */ - size_t len = strlen(path) + strlen(filename) + 6; - CALLOC(tempfile, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, NULL)); - snprintf(tempfile, len, "%s%s.part", path, filename); +#define check_stop() if(dload_interrupted) { ret = -1; goto cleanup; } +enum sighandlers { OLD = 0, NEW = 1 }; - return(tempfile); +static int dload_interrupted; +static void inthandler(int UNUSED signum) +{ + dload_interrupted = 1; } -static const char *gethost(struct url *fileurl) +static int curl_progress(void *file, double dltotal, double dlnow, + double UNUSED ultotal, double UNUSED ulnow) { - const char *host = _("disk"); - if(strcmp(SCHEME_FILE, fileurl->scheme) != 0) { - host = fileurl->host; + struct fileinfo *dlfile = (struct fileinfo *)file; + double current_size, total_size; + + /* SIGINT sent, abort by alerting curl */ + if(dload_interrupted) { + return 1; + } + + /* none of what follows matters if the front end has no callback */ + if(dlfile->handle->dlcb == NULL) { + return 0; + } + + current_size = dlfile->initial_size + dlnow; + total_size = dlfile->initial_size + dltotal; + + if(DOUBLE_EQ(dltotal, 0) || DOUBLE_EQ(prevprogress, total_size)) { + return 0; + } + + /* initialize the progress bar here to avoid displaying it when + * a repo is up to date and nothing gets downloaded */ + if(DOUBLE_EQ(prevprogress, 0)) { + dlfile->handle->dlcb(dlfile->filename, 0, (long)dltotal); } - return(host); + + dlfile->handle->dlcb(dlfile->filename, (long)current_size, (long)total_size); + + prevprogress = current_size; + + return 0; } -int dload_interrupted; -static void inthandler(int signum) +static int curl_gethost(const char *url, char *buffer) { - dload_interrupted = 1; + size_t hostlen; + char *p; + + if(strncmp(url, "file://", 7) == 0) { + strcpy(buffer, _("disk")); + } else { + p = strstr(url, "//"); + if(!p) { + return 1; + } + p += 2; /* jump over the found // */ + hostlen = strcspn(p, "/"); + if(hostlen > 255) { + /* buffer overflow imminent */ + return 1; + } + snprintf(buffer, hostlen + 1, "%s", p); + } + + return 0; } -#define check_stop() if(dload_interrupted) { ret = -1; goto cleanup; } -enum sighandlers { OLD = 0, NEW = 1 }; +static int utimes_long(const char *path, long time) +{ + if(time != -1) { + struct timeval tv[2]; + memset(&tv, 0, sizeof(tv)); + tv[0].tv_sec = tv[1].tv_sec = time; + return utimes(path, tv); + } + return 0; +} -static int download_internal(const char *url, const char *localpath, - int force) { + +static int curl_download_internal(pmhandle_t *handle, + const char *url, const char *localpath, + int force, int allow_resume, int errors_ok) +{ + int ret = -1; FILE *localf = NULL; + const char *useragent; + const char *open_mode = "wb"; + char *destfile, *tempfile; + /* RFC1123 states applications should support this length */ + char hostname[256]; + char error_buffer[CURL_ERROR_SIZE]; struct stat st; - int ret = 0; - off_t dl_thisfile = 0; - ssize_t nread = 0; - char *tempfile, *destfile, *filename; + long timecond, remote_time; + double remote_size, bytes_dl; struct sigaction sig_pipe[2], sig_int[2]; - - off_t local_size = 0; - time_t local_time = 0; - - struct url *fileurl; - struct url_stat ust; - fetchIO *dlf = NULL; - - char buffer[PM_DLBUF_LEN]; - - filename = get_filename(url); - if(!filename) { - _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); - RET_ERR(PM_ERR_SERVER_BAD_URL, -1); + struct fileinfo dlfile; + + dlfile.handle = handle; + dlfile.initial_size = 0.0; + dlfile.filename = get_filename(url); + if(!dlfile.filename || curl_gethost(url, hostname) != 0) { + _alpm_log(handle, PM_LOG_ERROR, _("url '%s' is invalid\n"), url); + RET_ERR(handle, PM_ERR_SERVER_BAD_URL, -1); } - fileurl = fetchParseURL(url); - if(!fileurl) { - _alpm_log(PM_LOG_ERROR, _("url '%s' is invalid\n"), url); - RET_ERR(PM_ERR_LIBFETCH, -1); + destfile = get_fullpath(localpath, dlfile.filename, ""); + tempfile = get_fullpath(localpath, dlfile.filename, ".part"); + if(!destfile || !tempfile) { + goto cleanup; } - destfile = get_destfile(localpath, filename); - tempfile = get_tempfile(localpath, filename); - - if(stat(tempfile, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0) { - _alpm_log(PM_LOG_DEBUG, "tempfile found, attempting continuation\n"); - local_time = fileurl->last_modified = st.st_mtime; - local_size = fileurl->offset = (off_t)st.st_size; - dl_thisfile = st.st_size; - localf = fopen(tempfile, "ab"); - } else if(!force && stat(destfile, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0) { - _alpm_log(PM_LOG_DEBUG, "destfile found, using mtime only\n"); - local_time = fileurl->last_modified = st.st_mtime; - local_size = /* no fu->off here */ (off_t)st.st_size; - } else { - _alpm_log(PM_LOG_DEBUG, "no file found matching criteria, starting from scratch\n"); + error_buffer[0] = '\0'; + + /* the curl_easy handle is initialized with the alpm handle, so we only need + * to reset the curl handle set parameters for each time it's used. */ + curl_easy_reset(handle->curl); + curl_easy_setopt(handle->curl, CURLOPT_URL, url); + curl_easy_setopt(handle->curl, CURLOPT_FAILONERROR, 1L); + curl_easy_setopt(handle->curl, CURLOPT_ERRORBUFFER, error_buffer); + curl_easy_setopt(handle->curl, CURLOPT_CONNECTTIMEOUT, 10L); + curl_easy_setopt(handle->curl, CURLOPT_FILETIME, 1L); + curl_easy_setopt(handle->curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(handle->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(handle->curl, CURLOPT_PROGRESSFUNCTION, curl_progress); + curl_easy_setopt(handle->curl, CURLOPT_PROGRESSDATA, (void *)&dlfile); + curl_easy_setopt(handle->curl, CURLOPT_LOW_SPEED_LIMIT, 1024L); + curl_easy_setopt(handle->curl, CURLOPT_LOW_SPEED_TIME, 10L); + + useragent = getenv("HTTP_USER_AGENT"); + if(useragent != NULL) { + curl_easy_setopt(handle->curl, CURLOPT_USERAGENT, useragent); } - /* pass the raw filename for passing to the callback function */ - _alpm_log(PM_LOG_DEBUG, "using '%s' for download progress\n", filename); + if(!allow_resume && !force && stat(destfile, &st) == 0) { + /* start from scratch, but only download if our local is out of date. */ + curl_easy_setopt(handle->curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE); + curl_easy_setopt(handle->curl, CURLOPT_TIMEVALUE, (long)st.st_mtime); + } else if(stat(tempfile, &st) == 0 && allow_resume) { + /* a previous partial download exists, resume from end of file. */ + open_mode = "ab"; + curl_easy_setopt(handle->curl, CURLOPT_RESUME_FROM, (long)st.st_size); + _alpm_log(handle, PM_LOG_DEBUG, "tempfile found, attempting continuation"); + dlfile.initial_size = (double)st.st_size; + } - /* print proxy info for debug purposes */ - _alpm_log(PM_LOG_DEBUG, "HTTP_PROXY: %s\n", getenv("HTTP_PROXY")); - _alpm_log(PM_LOG_DEBUG, "http_proxy: %s\n", getenv("http_proxy")); - _alpm_log(PM_LOG_DEBUG, "FTP_PROXY: %s\n", getenv("FTP_PROXY")); - _alpm_log(PM_LOG_DEBUG, "ftp_proxy: %s\n", getenv("ftp_proxy")); + localf = fopen(tempfile, open_mode); + if(localf == NULL) { + goto cleanup; + } - /* 10s timeout */ - fetchTimeout = 10; + curl_easy_setopt(handle->curl, CURLOPT_WRITEDATA, localf); /* ignore any SIGPIPE signals- these may occur if our FTP socket dies or * something along those lines. Store the old signal handler first. */ @@ -169,168 +237,67 @@ static int download_internal(const char *url, const char *localpath, sigaction(SIGINT, NULL, &sig_int[OLD]); sigaction(SIGINT, &sig_int[NEW], NULL); - /* NOTE: libfetch does not reset the error code, be sure to do it before - * calls into the library */ - - /* TODO: if we call fetchStat() and get a redirect (disabling automagic - * redirect following), we should repeat the file locator stuff and get a new - * filename rather than only base if off the first URL, and then verify - * get_filename() didn't return ''. Of course, libfetch might not even allow - * us to even get that URL...FS#22645. This would allow us to download things - * without totally puking like - * http://www.archlinux.org/packages/community/x86_64/exim/download/ */ - - /* find out the remote size *and* mtime in one go. there is a lot of - * trouble in trying to do both size and "if-modified-since" logic in a - * non-stat request, so avoid it. */ - fetchLastErrCode = 0; - if(fetchStat(fileurl, &ust, "") == -1) { - pm_errno = PM_ERR_LIBFETCH; - _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), - filename, gethost(fileurl), fetchLastErrString); - ret = -1; - goto cleanup; - } - check_stop(); - - _alpm_log(PM_LOG_DEBUG, "ust.mtime: %ld local_time: %ld compare: %ld\n", - ust.mtime, local_time, local_time - ust.mtime); - _alpm_log(PM_LOG_DEBUG, "ust.size: %jd local_size: %jd compare: %jd\n", - (intmax_t)ust.size, (intmax_t)local_size, (intmax_t)(local_size - ust.size)); - if(!force && ust.mtime && ust.mtime == local_time - && ust.size && ust.size == local_size) { - /* the remote time and size values agreed with what we have, so move on - * because there is nothing more to do. */ - _alpm_log(PM_LOG_DEBUG, "files are identical, skipping %s\n", filename); - ret = 1; - goto cleanup; - } - if(!ust.mtime || ust.mtime != local_time) { - _alpm_log(PM_LOG_DEBUG, "mtimes were different or unavailable, downloading %s from beginning\n", filename); - fileurl->offset = 0; - } + /* Progress 0 - initialize */ + prevprogress = 0; - fetchLastErrCode = 0; - dlf = fetchGet(fileurl, ""); - check_stop(); + /* perform transfer */ + handle->curlerr = curl_easy_perform(handle->curl); - if(fetchLastErrCode != 0 || dlf == NULL) { - pm_errno = PM_ERR_LIBFETCH; - _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), - filename, gethost(fileurl), fetchLastErrString); - ret = -1; + /* was it a success? */ + if(handle->curlerr == CURLE_ABORTED_BY_CALLBACK) { goto cleanup; - } else { - _alpm_log(PM_LOG_DEBUG, "connected to %s successfully\n", fileurl->host); - } - - if(localf && fileurl->offset == 0) { - _alpm_log(PM_LOG_WARNING, _("resuming download of %s not possible; starting over\n"), filename); - fclose(localf); - localf = NULL; - } else if(fileurl->offset) { - _alpm_log(PM_LOG_DEBUG, "resuming download at position %jd\n", (intmax_t)fileurl->offset); - } - - - if(localf == NULL) { - _alpm_rmrf(tempfile); - fileurl->offset = (off_t)0; - dl_thisfile = 0; - localf = fopen(tempfile, "wb"); - if(localf == NULL) { /* still null? */ - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - tempfile, strerror(errno)); - ret = -1; - goto cleanup; + } else if(handle->curlerr != CURLE_OK) { + if(!errors_ok) { + handle->pm_errno = PM_ERR_LIBCURL; + _alpm_log(handle, PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"), + dlfile.filename, hostname, error_buffer); + } else { + _alpm_log(handle, PM_LOG_DEBUG, "failed retrieving file '%s' from %s : %s\n", + dlfile.filename, hostname, error_buffer); } + unlink(tempfile); + goto cleanup; } - /* Progress 0 - initialize */ - if(handle->dlcb) { - handle->dlcb(filename, 0, ust.size); - } - - while((nread = fetchIO_read(dlf, buffer, PM_DLBUF_LEN)) > 0) { - check_stop(); - size_t nwritten = 0; - nwritten = fwrite(buffer, 1, (size_t)nread, localf); - if((nwritten != (size_t)nread) || ferror(localf)) { - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - tempfile, strerror(errno)); - ret = -1; - goto cleanup; - } - dl_thisfile += nread; - - if(handle->dlcb) { - handle->dlcb(filename, dl_thisfile, ust.size); - } - } + /* retrieve info about the state of the transfer */ + curl_easy_getinfo(handle->curl, CURLINFO_FILETIME, &remote_time); + curl_easy_getinfo(handle->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &remote_size); + curl_easy_getinfo(handle->curl, CURLINFO_SIZE_DOWNLOAD, &bytes_dl); + curl_easy_getinfo(handle->curl, CURLINFO_CONDITION_UNMET, &timecond); - /* did the transfer complete normally? */ - if (nread == -1) { - /* not PM_ERR_LIBFETCH here because libfetch error string might be empty */ - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s\n"), - filename, gethost(fileurl)); - ret = -1; + /* time condition was met and we didn't download anything. we need to + * clean up the 0 byte .part file that's left behind. */ + if(timecond == 1 && DOUBLE_EQ(bytes_dl, 0)) { + ret = 1; + unlink(tempfile); goto cleanup; } - if (ust.size != -1 && dl_thisfile < ust.size) { - pm_errno = PM_ERR_RETRIEVE; - _alpm_log(PM_LOG_ERROR, _("%s appears to be truncated: %jd/%jd bytes\n"), - filename, (intmax_t)dl_thisfile, (intmax_t)ust.size); - ret = -1; + /* remote_size isn't necessarily the full size of the file, just what the + * server reported as remaining to download. compare it to what curl reported + * as actually being transferred during curl_easy_perform() */ + if(!DOUBLE_EQ(remote_size, -1) && !DOUBLE_EQ(bytes_dl, -1) && + !DOUBLE_EQ(bytes_dl, remote_size)) { + handle->pm_errno = PM_ERR_RETRIEVE; + _alpm_log(handle, PM_LOG_ERROR, _("%s appears to be truncated: %jd/%jd bytes\n"), + dlfile.filename, (intmax_t)bytes_dl, (intmax_t)remote_size); goto cleanup; } - /* probably safer to close the file descriptors now before renaming the file, - * for example to make sure the buffers are flushed. - */ - fclose(localf); - localf = NULL; - fetchIO_close(dlf); - dlf = NULL; - - /* set the times on the file to the same as that of the remote file */ - if(ust.mtime) { - struct timeval tv[2]; - memset(&tv, 0, sizeof(tv)); - tv[0].tv_sec = ust.atime; - tv[1].tv_sec = ust.mtime; - utimes(tempfile, tv); - } - if(rename(tempfile, destfile)) { - _alpm_log(PM_LOG_ERROR, _("could not rename %s to %s (%s)\n"), - tempfile, destfile, strerror(errno)); - ret = -1; - } ret = 0; cleanup: - FREE(tempfile); - FREE(destfile); if(localf != NULL) { - /* if we still had a local file open, we got interrupted. set the mtimes on - * the file accordingly. */ - fflush(localf); - if(ust.mtime) { - struct timeval tv[2]; - memset(&tv, 0, sizeof(tv)); - tv[0].tv_sec = ust.atime; - tv[1].tv_sec = ust.mtime; - futimes(fileno(localf), tv); - } fclose(localf); + utimes_long(tempfile, remote_time); } - if(dlf != NULL) { - fetchIO_close(dlf); + + if(ret == 0) { + rename(tempfile, destfile); } - fetchFreeURL(fileurl); + + FREE(tempfile); + FREE(destfile); /* restore the old signal handlers */ sigaction(SIGINT, &sig_int[OLD], NULL); @@ -340,106 +307,76 @@ cleanup: raise(SIGINT); } - return(ret); + return ret; } #endif -static int download(const char *url, const char *localpath, - int force) { +int _alpm_download(pmhandle_t *handle, const char *url, const char *localpath, + int force, int allow_resume, int errors_ok) +{ if(handle->fetchcb == NULL) { -#ifdef HAVE_LIBFETCH - return(download_internal(url, localpath, force)); +#ifdef HAVE_LIBCURL + return curl_download_internal(handle, url, localpath, + force, allow_resume, errors_ok); #else - RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); + RET_ERR(handle, PM_ERR_EXTERNAL_DOWNLOAD, -1); #endif } else { int ret = handle->fetchcb(url, localpath, force); - if(ret == -1) { - RET_ERR(PM_ERR_EXTERNAL_DOWNLOAD, -1); + if(ret == -1 && !errors_ok) { + RET_ERR(handle, PM_ERR_EXTERNAL_DOWNLOAD, -1); } - return(ret); + return ret; } } -/* - * Download a single file - * - servers must be a list of urls WITHOUT trailing slashes. - * - * RETURN: 0 for successful download - * 1 if the files are identical - * -1 on error - */ -int _alpm_download_single_file(const char *filename, - alpm_list_t *servers, const char *localpath, - int force) -{ - alpm_list_t *i; - int ret = -1; - - ASSERT(servers != NULL, RET_ERR(PM_ERR_SERVER_NONE, -1)); - - for(i = servers; i; i = i->next) { - const char *server = i->data; - char *fileurl = NULL; - size_t len; - - /* print server + filename into a buffer */ - len = strlen(server) + strlen(filename) + 2; - CALLOC(fileurl, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); - snprintf(fileurl, len, "%s/%s", server, filename); - - ret = download(fileurl, localpath, force); - FREE(fileurl); - if(ret != -1) { - break; - } - } - - return(ret); -} - -int _alpm_download_files(alpm_list_t *files, - alpm_list_t *servers, const char *localpath) -{ - int ret = 0; - alpm_list_t *lp; - - for(lp = files; lp; lp = lp->next) { - char *filename = lp->data; - if(_alpm_download_single_file(filename, servers, - localpath, 0) == -1) { - ret++; - } - } - - return(ret); -} - /** Fetch a remote pkg. */ -char SYMEXPORT *alpm_fetch_pkgurl(const char *url) +char SYMEXPORT *alpm_fetch_pkgurl(pmhandle_t *handle, const char *url) { - char *filename, *filepath; - const char *cachedir; + char *filepath; + const char *filename, *cachedir; int ret; - ALPM_LOG_FUNC; + CHECK_HANDLE(handle, return NULL); filename = get_filename(url); /* find a valid cache dir to download to */ - cachedir = _alpm_filecache_setup(); + cachedir = _alpm_filecache_setup(handle); /* download the file */ - ret = download(url, cachedir, 0); + ret = _alpm_download(handle, url, cachedir, 0, 1, 0); if(ret == -1) { - _alpm_log(PM_LOG_WARNING, _("failed to download %s\n"), url); - return(NULL); + _alpm_log(handle, PM_LOG_WARNING, _("failed to download %s\n"), url); + return NULL; + } + _alpm_log(handle, PM_LOG_DEBUG, "successfully downloaded %s\n", url); + + /* attempt to download the signature */ + if(ret == 0 && (handle->sigverify == PM_PGP_VERIFY_ALWAYS || + handle->sigverify == PM_PGP_VERIFY_OPTIONAL)) { + char *sig_url; + size_t len; + int errors_ok = (handle->sigverify == PM_PGP_VERIFY_OPTIONAL); + + len = strlen(url) + 5; + CALLOC(sig_url, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, NULL)); + snprintf(sig_url, len, "%s.sig", url); + + ret = _alpm_download(handle, sig_url, cachedir, 1, 0, errors_ok); + if(ret == -1 && !errors_ok) { + _alpm_log(handle, PM_LOG_WARNING, _("failed to download %s\n"), sig_url); + /* Warn now, but don't return NULL. We will fail later during package + * load time. */ + } else if(ret == 0) { + _alpm_log(handle, PM_LOG_DEBUG, "successfully downloaded %s\n", sig_url); + } + FREE(sig_url); } - _alpm_log(PM_LOG_DEBUG, "successfully downloaded %s\n", url); /* we should be able to find the file the second time around */ - filepath = _alpm_filecache_find(filename); - return(filepath); + filepath = _alpm_filecache_find(handle, filename); + return filepath; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h index 63266491..e409c32b 100644 --- a/lib/libalpm/dload.h +++ b/lib/libalpm/dload.h @@ -25,14 +25,15 @@ #include <time.h> -#define PM_DLBUF_LEN (1024 * 16) +/* internal structure for communicating with curl progress callback */ +struct fileinfo { + pmhandle_t *handle; + const char *filename; + double initial_size; +}; -int _alpm_download_single_file(const char *filename, - alpm_list_t *servers, const char *localpath, - int force); - -int _alpm_download_files(alpm_list_t *files, - alpm_list_t *servers, const char *localpath); +int _alpm_download(pmhandle_t *handle, const char *url, const char *localpath, + int force, int allow_resume, int errors_ok); #endif /* _ALPM_DLOAD_H */ diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c index 21fbb48f..d893f866 100644 --- a/lib/libalpm/error.c +++ b/lib/libalpm/error.c @@ -20,28 +20,21 @@ #include "config.h" -/* TODO: needed for the libfetch stuff, unfortunately- we should kill it */ -#include <stdio.h> -/* the following two are needed for FreeBSD's libfetch */ -#include <limits.h> /* PATH_MAX */ -#if defined(HAVE_SYS_PARAM_H) -#include <sys/param.h> /* MAXHOSTNAMELEN */ -#endif - -#ifdef HAVE_LIBFETCH -#include <fetch.h> /* fetchLastErrString */ +#ifdef HAVE_LIBCURL +#include <curl/curl.h> #endif /* libalpm */ #include "util.h" #include "alpm.h" +#include "handle.h" -const char SYMEXPORT *alpm_strerrorlast(void) +enum _pmerrno_t SYMEXPORT alpm_errno(pmhandle_t *handle) { - return alpm_strerror(pm_errno); + return handle->pm_errno; } -const char SYMEXPORT *alpm_strerror(int err) +const char SYMEXPORT *alpm_strerror(enum _pmerrno_t err) { switch(err) { /* System */ @@ -122,6 +115,13 @@ const char SYMEXPORT *alpm_strerror(int err) return _("package architecture is not valid"); case PM_ERR_PKG_REPO_NOT_FOUND: return _("could not find repository for target"); + /* Signatures */ + case PM_ERR_SIG_MISSINGDIR: + return _("signature directory not configured correctly"); + case PM_ERR_SIG_INVALID: + return _("invalid PGP signature"); + case PM_ERR_SIG_UNKNOWN: + return _("unknown PGP signature"); /* Deltas */ case PM_ERR_DLT_INVALID: return _("invalid or corrupted delta"); @@ -137,8 +137,6 @@ const char SYMEXPORT *alpm_strerror(int err) /* Miscellaenous */ case PM_ERR_RETRIEVE: return _("failed to retrieve some files"); - case PM_ERR_WRITE: - return _("failed to copy some file"); case PM_ERR_INVALID_REGEX: return _("invalid regular expression"); /* Errors from external libraries- our own wrapper error */ @@ -147,13 +145,10 @@ const char SYMEXPORT *alpm_strerror(int err) * requires the archive struct, so we can't. Just use a generic * error string instead. */ return _("libarchive error"); - case PM_ERR_LIBFETCH: -#ifdef HAVE_LIBFETCH - return fetchLastErrString; -#else - /* obviously shouldn't get here... */ + case PM_ERR_LIBCURL: return _("download library error"); -#endif + case PM_ERR_GPGME: + return _("gpgme error"); case PM_ERR_EXTERNAL_DOWNLOAD: return _("error invoking external downloader"); /* Unknown error! */ diff --git a/lib/libalpm/graph.c b/lib/libalpm/graph.c new file mode 100644 index 00000000..fc2c9e16 --- /dev/null +++ b/lib/libalpm/graph.c @@ -0,0 +1,41 @@ +/* + * graph.c - helpful graph structure and setup/teardown methods + * + * Copyright (c) 2007-2011 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include "graph.h" +#include "util.h" +#include "log.h" + +pmgraph_t *_alpm_graph_new(void) +{ + pmgraph_t *graph = NULL; + + CALLOC(graph, 1, sizeof(pmgraph_t), return NULL); + return graph; +} + +void _alpm_graph_free(void *data) +{ + pmgraph_t *graph = data; + alpm_list_free(graph->children); + free(graph); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/graph.h b/lib/libalpm/graph.h index 07986f66..f76c6004 100644 --- a/lib/libalpm/graph.h +++ b/lib/libalpm/graph.h @@ -1,8 +1,7 @@ /* * graph.h - helpful graph structure and setup/teardown methods * - * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> - * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> + * Copyright (c) 2007-2011 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,34 +16,27 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#ifndef _ALPM_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" -#include "util.h" /* CALLOC() */ -struct __pmgraph_t { +typedef struct __pmgraph_t { char state; /* 0: untouched, -1: entered, other: leaving time */ - void *data; off_t weight; /* weight of the node */ + void *data; struct __pmgraph_t *parent; /* where did we come from? */ alpm_list_t *children; alpm_list_t *childptr; /* points to a child in children list */ -}; -typedef struct __pmgraph_t pmgraph_t; - -static pmgraph_t *_alpm_graph_new(void) -{ - pmgraph_t *graph = NULL; +} pmgraph_t; - CALLOC(graph, 1, sizeof(pmgraph_t), RET_ERR(PM_ERR_MEMORY, NULL)); - return(graph); -} +pmgraph_t *_alpm_graph_new(void); +void _alpm_graph_free(void *data); -static void _alpm_graph_free(void *data) -{ - pmgraph_t *graph = data; - alpm_list_free(graph->children); - free(graph); -} +#endif /* _ALPM_GRAPH_H */ +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/group.c b/lib/libalpm/group.c index 398c2588..13a216ee 100644 --- a/lib/libalpm/group.c +++ b/lib/libalpm/group.c @@ -21,7 +21,6 @@ #include "config.h" #include <stdlib.h> -#include <stdio.h> #include <string.h> /* libalpm */ @@ -35,18 +34,14 @@ pmgrp_t *_alpm_grp_new(const char *name) { pmgrp_t* grp; - ALPM_LOG_FUNC; + CALLOC(grp, 1, sizeof(pmgrp_t), return NULL); + STRDUP(grp->name, name, free(grp); return NULL); - CALLOC(grp, 1, sizeof(pmgrp_t), RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(grp->name, name, RET_ERR(PM_ERR_MEMORY, NULL)); - - return(grp); + return grp; } void _alpm_grp_free(pmgrp_t *grp) { - ALPM_LOG_FUNC; - if(grp == NULL) { return; } @@ -59,21 +54,14 @@ void _alpm_grp_free(pmgrp_t *grp) const char SYMEXPORT *alpm_grp_get_name(const pmgrp_t *grp) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(grp != NULL, return(NULL)); - + ASSERT(grp != NULL, return NULL); return grp->name; } alpm_list_t SYMEXPORT *alpm_grp_get_pkgs(const pmgrp_t *grp) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(grp != NULL, return(NULL)); - + ASSERT(grp != NULL, return NULL); return grp->packages; } + /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 586aad1e..d2bb4f61 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -27,9 +27,7 @@ #include <limits.h> #include <sys/types.h> #include <syslog.h> -#include <time.h> #include <sys/stat.h> -#include <errno.h> /* libalpm */ #include "handle.h" @@ -39,22 +37,19 @@ #include "trans.h" #include "alpm.h" -/* global var for handle (private to libalpm) */ -pmhandle_t *handle = NULL; - pmhandle_t *_alpm_handle_new() { pmhandle_t *handle; - CALLOC(handle, 1, sizeof(pmhandle_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(handle, 1, sizeof(pmhandle_t), return NULL); + + handle->sigverify = PM_PGP_VERIFY_OPTIONAL; - return(handle); + return handle; } void _alpm_handle_free(pmhandle_t *handle) { - ALPM_LOG_FUNC; - if(handle == NULL) { return; } @@ -69,6 +64,11 @@ void _alpm_handle_free(pmhandle_t *handle) closelog(); } +#ifdef HAVE_LIBCURL + /* release curl handle */ + curl_easy_cleanup(handle->curl); +#endif + /* free memory */ _alpm_trans_free(handle->trans); FREE(handle->root); @@ -77,6 +77,7 @@ void _alpm_handle_free(pmhandle_t *handle) FREE(handle->logfile); FREE(handle->lockfile); FREE(handle->arch); + FREE(handle->signaturedir); FREELIST(handle->dbs_sync); FREELIST(handle->noupgrade); FREELIST(handle->noextract); @@ -85,336 +86,240 @@ void _alpm_handle_free(pmhandle_t *handle) FREE(handle); } -alpm_cb_log SYMEXPORT alpm_option_get_logcb() +alpm_cb_log SYMEXPORT alpm_option_get_logcb(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->logcb; } -alpm_cb_download SYMEXPORT alpm_option_get_dlcb() +alpm_cb_download SYMEXPORT alpm_option_get_dlcb(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->dlcb; } -alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb() +alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->fetchcb; } -alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb() +alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->totaldlcb; } -const char SYMEXPORT *alpm_option_get_root() +const char SYMEXPORT *alpm_option_get_root(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->root; } -const char SYMEXPORT *alpm_option_get_dbpath() +const char SYMEXPORT *alpm_option_get_dbpath(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->dbpath; } -alpm_list_t SYMEXPORT *alpm_option_get_cachedirs() +alpm_list_t SYMEXPORT *alpm_option_get_cachedirs(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->cachedirs; } -const char SYMEXPORT *alpm_option_get_logfile() +const char SYMEXPORT *alpm_option_get_logfile(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->logfile; } -const char SYMEXPORT *alpm_option_get_lockfile() +const char SYMEXPORT *alpm_option_get_lockfile(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->lockfile; } -int SYMEXPORT alpm_option_get_usesyslog() +const char SYMEXPORT *alpm_option_get_signaturedir(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return -1; - } + CHECK_HANDLE(handle, return NULL); + return handle->signaturedir; +} + +int SYMEXPORT alpm_option_get_usesyslog(pmhandle_t *handle) +{ + CHECK_HANDLE(handle, return -1); return handle->usesyslog; } -alpm_list_t SYMEXPORT *alpm_option_get_noupgrades() +alpm_list_t SYMEXPORT *alpm_option_get_noupgrades(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->noupgrade; } -alpm_list_t SYMEXPORT *alpm_option_get_noextracts() +alpm_list_t SYMEXPORT *alpm_option_get_noextracts(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->noextract; } -alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs() +alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->ignorepkg; } -alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps() +alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->ignoregrp; } -const char SYMEXPORT *alpm_option_get_arch() +const char SYMEXPORT *alpm_option_get_arch(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->arch; } -int SYMEXPORT alpm_option_get_usedelta() +int SYMEXPORT alpm_option_get_usedelta(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return -1; - } + CHECK_HANDLE(handle, return -1); return handle->usedelta; } -int SYMEXPORT alpm_option_get_checkspace() +int SYMEXPORT alpm_option_get_checkspace(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return -1; - } + CHECK_HANDLE(handle, return -1); return handle->checkspace; } -pmdb_t SYMEXPORT *alpm_option_get_localdb() +pmdb_t SYMEXPORT *alpm_option_get_localdb(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->db_local; } -alpm_list_t SYMEXPORT *alpm_option_get_syncdbs() +alpm_list_t SYMEXPORT *alpm_option_get_syncdbs(pmhandle_t *handle) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return NULL; - } + CHECK_HANDLE(handle, return NULL); return handle->dbs_sync; } -void SYMEXPORT alpm_option_set_logcb(alpm_cb_log cb) +int SYMEXPORT alpm_option_set_logcb(pmhandle_t *handle, alpm_cb_log cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->logcb = cb; + return 0; } -void SYMEXPORT alpm_option_set_dlcb(alpm_cb_download cb) +int SYMEXPORT alpm_option_set_dlcb(pmhandle_t *handle, alpm_cb_download cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->dlcb = cb; + return 0; } -void SYMEXPORT alpm_option_set_fetchcb(alpm_cb_fetch cb) +int SYMEXPORT alpm_option_set_fetchcb(pmhandle_t *handle, alpm_cb_fetch cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->fetchcb = cb; + return 0; } -void SYMEXPORT alpm_option_set_totaldlcb(alpm_cb_totaldl cb) +int SYMEXPORT alpm_option_set_totaldlcb(pmhandle_t *handle, alpm_cb_totaldl cb) { - if (handle == NULL) { - pm_errno = PM_ERR_HANDLE_NULL; - return; - } + CHECK_HANDLE(handle, return -1); handle->totaldlcb = cb; + return 0; } -int SYMEXPORT alpm_option_set_root(const char *root) -{ - struct stat st; - char *realroot; - size_t rootlen; - - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); +static char *canonicalize_path(const char *path) { + char *new_path; + size_t len; - if(!root) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); + /* verify path ends in a '/' */ + len = strlen(path); + if(path[len - 1] != '/') { + len += 1; } - if(stat(root, &st) == -1 || !S_ISDIR(st.st_mode)) { - pm_errno = PM_ERR_NOT_A_DIR; - return(-1); - } - - realroot = calloc(PATH_MAX+1, sizeof(char)); - if(!realpath(root, realroot)) { - FREE(realroot); - pm_errno = PM_ERR_NOT_A_DIR; - return(-1); - } - - /* verify root ends in a '/' */ - rootlen = strlen(realroot); - if(realroot[rootlen-1] != '/') { - rootlen += 1; - } - if(handle->root) { - FREE(handle->root); - } - handle->root = calloc(rootlen + 1, sizeof(char)); - strncpy(handle->root, realroot, rootlen); - handle->root[rootlen-1] = '/'; - FREE(realroot); - _alpm_log(PM_LOG_DEBUG, "option 'root' = %s\n", handle->root); - return(0); + new_path = calloc(len + 1, sizeof(char)); + strncpy(new_path, path, len); + new_path[len - 1] = '/'; + return new_path; } -int SYMEXPORT alpm_option_set_dbpath(const char *dbpath) -{ +enum _pmerrno_t _alpm_set_directory_option(const char *value, + char **storage, int must_exist) + { struct stat st; - size_t dbpathlen, lockfilelen; - const char *lf = "db.lck"; - - ALPM_LOG_FUNC; + char *real = NULL; + const char *path; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - if(!dbpath) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); - } - if(stat(dbpath, &st) == -1 || !S_ISDIR(st.st_mode)) { - pm_errno = PM_ERR_NOT_A_DIR; - return(-1); - } - /* verify dbpath ends in a '/' */ - dbpathlen = strlen(dbpath); - if(dbpath[dbpathlen-1] != '/') { - dbpathlen += 1; + path = value; + if(!path) { + return PM_ERR_WRONG_ARGS; } - if(handle->dbpath) { - FREE(handle->dbpath); + if(must_exist) { + if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { + return PM_ERR_NOT_A_DIR; + } + real = calloc(PATH_MAX, sizeof(char)); + if(!realpath(path, real)) { + free(real); + return PM_ERR_NOT_A_DIR; + } + path = real; } - handle->dbpath = calloc(dbpathlen+1, sizeof(char)); - strncpy(handle->dbpath, dbpath, dbpathlen); - handle->dbpath[dbpathlen-1] = '/'; - _alpm_log(PM_LOG_DEBUG, "option 'dbpath' = %s\n", handle->dbpath); - if(handle->lockfile) { - FREE(handle->lockfile); + if(*storage) { + FREE(*storage); } - lockfilelen = strlen(handle->dbpath) + strlen(lf) + 1; - handle->lockfile = calloc(lockfilelen, sizeof(char)); - snprintf(handle->lockfile, lockfilelen, "%s%s", handle->dbpath, lf); - _alpm_log(PM_LOG_DEBUG, "option 'lockfile' = %s\n", handle->lockfile); - return(0); + *storage = canonicalize_path(path); + free(real); + return 0; } -int SYMEXPORT alpm_option_add_cachedir(const char *cachedir) +int SYMEXPORT alpm_option_add_cachedir(pmhandle_t *handle, const char *cachedir) { char *newcachedir; - size_t cachedirlen; - - ALPM_LOG_FUNC; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); if(!cachedir) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); + handle->pm_errno = PM_ERR_WRONG_ARGS; + return -1; } /* don't stat the cachedir yet, as it may not even be needed. we can * fail later if it is needed and the path is invalid. */ - /* verify cachedir ends in a '/' */ - cachedirlen = strlen(cachedir); - if(cachedir[cachedirlen-1] != '/') { - cachedirlen += 1; - } - newcachedir = calloc(cachedirlen + 1, sizeof(char)); - strncpy(newcachedir, cachedir, cachedirlen); - newcachedir[cachedirlen-1] = '/'; + newcachedir = canonicalize_path(cachedir); handle->cachedirs = alpm_list_add(handle->cachedirs, newcachedir); - _alpm_log(PM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir); - return(0); + _alpm_log(handle, PM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir); + return 0; } -void SYMEXPORT alpm_option_set_cachedirs(alpm_list_t *cachedirs) +int SYMEXPORT alpm_option_set_cachedirs(pmhandle_t *handle, alpm_list_t *cachedirs) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); - if(handle->cachedirs) FREELIST(handle->cachedirs); - if(cachedirs) handle->cachedirs = cachedirs; + alpm_list_t *i; + CHECK_HANDLE(handle, return -1); + if(handle->cachedirs) { + FREELIST(handle->cachedirs); + } + for(i = cachedirs; i; i = i->next) { + int ret = alpm_option_add_cachedir(handle, i->data); + if(ret) { + return ret; + } + } + return 0; } -int SYMEXPORT alpm_option_remove_cachedir(const char *cachedir) +int SYMEXPORT alpm_option_remove_cachedir(pmhandle_t *handle, const char *cachedir) { char *vdata = NULL; char *newcachedir; size_t cachedirlen; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); /* verify cachedir ends in a '/' */ cachedirlen = strlen(cachedir); if(cachedir[cachedirlen-1] != '/') { @@ -427,21 +332,19 @@ int SYMEXPORT alpm_option_remove_cachedir(const char *cachedir) FREE(newcachedir); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -int SYMEXPORT alpm_option_set_logfile(const char *logfile) +int SYMEXPORT alpm_option_set_logfile(pmhandle_t *handle, const char *logfile) { char *oldlogfile = handle->logfile; - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); if(!logfile) { - pm_errno = PM_ERR_WRONG_ARGS; - return(-1); + handle->pm_errno = PM_ERR_WRONG_ARGS; + return -1; } handle->logfile = strdup(logfile); @@ -455,133 +358,180 @@ int SYMEXPORT alpm_option_set_logfile(const char *logfile) fclose(handle->logstream); handle->logstream = NULL; } - _alpm_log(PM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile); - return(0); + _alpm_log(handle, PM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile); + return 0; +} + +int SYMEXPORT alpm_option_set_signaturedir(pmhandle_t *handle, const char *signaturedir) +{ + CHECK_HANDLE(handle, return -1); + if(!signaturedir) { + handle->pm_errno = PM_ERR_WRONG_ARGS; + return -1; + } + + if(handle->signaturedir) { + FREE(handle->signaturedir); + } + handle->signaturedir = strdup(signaturedir); + + _alpm_log(handle, PM_LOG_DEBUG, "option 'signaturedir' = %s\n", handle->signaturedir); + return 0; } -void SYMEXPORT alpm_option_set_usesyslog(int usesyslog) +int SYMEXPORT alpm_option_set_usesyslog(pmhandle_t *handle, int usesyslog) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->usesyslog = usesyslog; + return 0; } -void SYMEXPORT alpm_option_add_noupgrade(const char *pkg) +int SYMEXPORT alpm_option_add_noupgrade(pmhandle_t *handle, const char *pkg) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->noupgrade = alpm_list_add(handle->noupgrade, strdup(pkg)); + return 0; } -void SYMEXPORT alpm_option_set_noupgrades(alpm_list_t *noupgrade) +int SYMEXPORT alpm_option_set_noupgrades(pmhandle_t *handle, alpm_list_t *noupgrade) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->noupgrade) FREELIST(handle->noupgrade); - if(noupgrade) handle->noupgrade = noupgrade; + handle->noupgrade = alpm_list_strdup(noupgrade); + return 0; } -int SYMEXPORT alpm_option_remove_noupgrade(const char *pkg) +int SYMEXPORT alpm_option_remove_noupgrade(pmhandle_t *handle, const char *pkg) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); handle->noupgrade = alpm_list_remove_str(handle->noupgrade, pkg, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_add_noextract(const char *pkg) +int SYMEXPORT alpm_option_add_noextract(pmhandle_t *handle, const char *pkg) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->noextract = alpm_list_add(handle->noextract, strdup(pkg)); + return 0; } -void SYMEXPORT alpm_option_set_noextracts(alpm_list_t *noextract) +int SYMEXPORT alpm_option_set_noextracts(pmhandle_t *handle, alpm_list_t *noextract) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->noextract) FREELIST(handle->noextract); - if(noextract) handle->noextract = noextract; + handle->noextract = alpm_list_strdup(noextract); + return 0; } -int SYMEXPORT alpm_option_remove_noextract(const char *pkg) +int SYMEXPORT alpm_option_remove_noextract(pmhandle_t *handle, const char *pkg) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); handle->noextract = alpm_list_remove_str(handle->noextract, pkg, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_add_ignorepkg(const char *pkg) +int SYMEXPORT alpm_option_add_ignorepkg(pmhandle_t *handle, const char *pkg) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->ignorepkg = alpm_list_add(handle->ignorepkg, strdup(pkg)); + return 0; } -void SYMEXPORT alpm_option_set_ignorepkgs(alpm_list_t *ignorepkgs) +int SYMEXPORT alpm_option_set_ignorepkgs(pmhandle_t *handle, alpm_list_t *ignorepkgs) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->ignorepkg) FREELIST(handle->ignorepkg); - if(ignorepkgs) handle->ignorepkg = ignorepkgs; + handle->ignorepkg = alpm_list_strdup(ignorepkgs); + return 0; } -int SYMEXPORT alpm_option_remove_ignorepkg(const char *pkg) +int SYMEXPORT alpm_option_remove_ignorepkg(pmhandle_t *handle, const char *pkg) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); handle->ignorepkg = alpm_list_remove_str(handle->ignorepkg, pkg, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_add_ignoregrp(const char *grp) +int SYMEXPORT alpm_option_add_ignoregrp(pmhandle_t *handle, const char *grp) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->ignoregrp = alpm_list_add(handle->ignoregrp, strdup(grp)); + return 0; } -void SYMEXPORT alpm_option_set_ignoregrps(alpm_list_t *ignoregrps) +int SYMEXPORT alpm_option_set_ignoregrps(pmhandle_t *handle, alpm_list_t *ignoregrps) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->ignoregrp) FREELIST(handle->ignoregrp); - if(ignoregrps) handle->ignoregrp = ignoregrps; + handle->ignoregrp = alpm_list_strdup(ignoregrps); + return 0; } -int SYMEXPORT alpm_option_remove_ignoregrp(const char *grp) +int SYMEXPORT alpm_option_remove_ignoregrp(pmhandle_t *handle, const char *grp) { char *vdata = NULL; - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); handle->ignoregrp = alpm_list_remove_str(handle->ignoregrp, grp, &vdata); if(vdata != NULL) { FREE(vdata); - return(1); + return 1; } - return(0); + return 0; } -void SYMEXPORT alpm_option_set_arch(const char *arch) +int SYMEXPORT alpm_option_set_arch(pmhandle_t *handle, const char *arch) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); if(handle->arch) FREE(handle->arch); - if(arch) handle->arch = strdup(arch); + if(arch) { + handle->arch = strdup(arch); + } else { + handle->arch = NULL; + } + return 0; } -void SYMEXPORT alpm_option_set_usedelta(int usedelta) +int SYMEXPORT alpm_option_set_usedelta(pmhandle_t *handle, int usedelta) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->usedelta = usedelta; + return 0; } -void SYMEXPORT alpm_option_set_checkspace(int checkspace) +int SYMEXPORT alpm_option_set_checkspace(pmhandle_t *handle, int checkspace) { - ASSERT(handle != NULL, RET_ERR_VOID(PM_ERR_HANDLE_NULL)); + CHECK_HANDLE(handle, return -1); handle->checkspace = checkspace; + return 0; +} + +int SYMEXPORT alpm_option_set_default_sigverify(pmhandle_t *handle, pgp_verify_t level) +{ + CHECK_HANDLE(handle, return -1); + ASSERT(level != PM_PGP_VERIFY_UNKNOWN, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); + handle->sigverify = level; + return 0; +} + +pgp_verify_t SYMEXPORT alpm_option_get_default_sigverify(pmhandle_t *handle) +{ + CHECK_HANDLE(handle, return PM_PGP_VERIFY_UNKNOWN); + return handle->sigverify; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index 2d962fe6..bace8052 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -24,12 +24,13 @@ #include <sys/types.h> #include "alpm_list.h" -#include "db.h" -#include "log.h" #include "alpm.h" -#include "trans.h" -typedef struct _pmhandle_t { +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#endif + +struct __pmhandle_t { /* internal usage */ pmdb_t *db_local; /* local db pointer */ alpm_list_t *dbs_sync; /* List of (pmdb_t *) */ @@ -37,6 +38,12 @@ typedef struct _pmhandle_t { FILE *lckstream; /* lock file stream pointer if one exists */ pmtrans_t *trans; +#ifdef HAVE_LIBCURL + /* libcurl handle */ + CURL *curl; /* reusable curl_easy handle */ + CURLcode curlerr; /* last error produced by curl */ +#endif + /* callback functions */ alpm_cb_log logcb; /* Log callback function */ alpm_cb_download dlcb; /* Download callback function */ @@ -48,6 +55,7 @@ typedef struct _pmhandle_t { char *dbpath; /* Base path to pacman's DBs */ char *logfile; /* Name of the log file */ char *lockfile; /* Name of the lock file */ + char *signaturedir; /* Directory where GnuPG files are stored */ alpm_list_t *cachedirs; /* Paths to pacman cache directories */ /* package lists */ @@ -57,18 +65,22 @@ typedef struct _pmhandle_t { alpm_list_t *ignoregrp; /* 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 */ - int checkspace; /* Check disk space before installing */ -} pmhandle_t; + 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 */ + int checkspace; /* Check disk space before installing */ + pgp_verify_t sigverify; /* Default signature verification level */ -/* global handle variable */ -extern pmhandle_t *handle; + /* error code */ + enum _pmerrno_t pm_errno; +}; pmhandle_t *_alpm_handle_new(void); void _alpm_handle_free(pmhandle_t *handle); +enum _pmerrno_t _alpm_set_directory_option(const char *value, + char **storage, int must_exist); + #endif /* _ALPM_HANDLE_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/log.c b/lib/libalpm/log.c index 09c6fb84..91bcb823 100644 --- a/lib/libalpm/log.c +++ b/lib/libalpm/log.c @@ -22,10 +22,7 @@ #include <stdio.h> #include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> #include <errno.h> -#include <time.h> /* libalpm */ #include "log.h" @@ -39,18 +36,16 @@ */ /** A printf-like function for logging. + * @param handle the context handle * @param fmt output format * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_logaction(const char *fmt, ...) +int SYMEXPORT alpm_logaction(pmhandle_t *handle, const char *fmt, ...) { int ret; va_list args; - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + ASSERT(handle != NULL, return -1); /* check if the logstream is open already, opening it if needed */ if(handle->logstream == NULL) { @@ -58,18 +53,18 @@ int SYMEXPORT alpm_logaction(const char *fmt, ...) /* if we couldn't open it, we have an issue */ if(handle->logstream == NULL) { if(errno == EACCES) { - pm_errno = PM_ERR_BADPERMS; + handle->pm_errno = PM_ERR_BADPERMS; } else if(errno == ENOENT) { - pm_errno = PM_ERR_NOT_A_DIR; + handle->pm_errno = PM_ERR_NOT_A_DIR; } else { - pm_errno = PM_ERR_SYSTEM; + handle->pm_errno = PM_ERR_SYSTEM; } - return(-1); + return -1; } } va_start(args, fmt); - ret = _alpm_logaction(handle->usesyslog, handle->logstream, fmt, args); + ret = _alpm_logaction(handle, fmt, args); va_end(args); /* TODO We should add a prefix to log strings depending on who called us. @@ -83,15 +78,15 @@ int SYMEXPORT alpm_logaction(const char *fmt, ...) * kpacman: "KPACMAN" * This would allow us to share the log file between several frontends * and know who does what */ - return(ret); + return ret; } /** @} */ -void _alpm_log(pmloglevel_t flag, const char *fmt, ...) +void _alpm_log(pmhandle_t *handle, pmloglevel_t flag, const char *fmt, ...) { va_list args; - alpm_cb_log logcb = alpm_option_get_logcb(); + alpm_cb_log logcb = alpm_option_get_logcb(handle); if(logcb == NULL) { return; diff --git a/lib/libalpm/log.h b/lib/libalpm/log.h index 9a2961fb..105430c4 100644 --- a/lib/libalpm/log.h +++ b/lib/libalpm/log.h @@ -22,14 +22,8 @@ #include "alpm.h" -#ifdef PACMAN_DEBUG -/* Log funtion entry points if debugging is enabled */ -#define ALPM_LOG_FUNC _alpm_log(PM_LOG_FUNCTION, "Enter %s\n", __func__) -#else -#define ALPM_LOG_FUNC -#endif - -void _alpm_log(pmloglevel_t flag, const char *fmt, ...) __attribute__((format(printf,2,3))); +void _alpm_log(pmhandle_t *handle, pmloglevel_t flag, + const char *fmt, ...) __attribute__((format(printf,3,4))); #endif /* _ALPM_LOG_H */ diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index f2f15af4..ff011982 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -23,13 +23,9 @@ #include "config.h" -#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <errno.h> #include <sys/types.h> -#include <sys/stat.h> /* libalpm */ #include "package.h" @@ -49,16 +45,14 @@ /** Free a package. */ int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg != NULL, return -1); /* Only free packages loaded in user space */ if(pkg->origin == PKG_FROM_FILE) { _alpm_pkg_free(pkg); } - return(0); + return 0; } /** Check the integrity (with md5) of a package from the sync cache. */ @@ -67,24 +61,24 @@ int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg) char *fpath; int retval; - ALPM_LOG_FUNC; - - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; /* We only inspect packages from sync repositories */ - ASSERT(pkg->origin == PKG_FROM_SYNCDB, RET_ERR(PM_ERR_PKG_INVALID, -1)); + ASSERT(pkg->origin == PKG_FROM_SYNCDB, + RET_ERR(pkg->handle, PM_ERR_WRONG_ARGS, -1)); - fpath = _alpm_filecache_find(alpm_pkg_get_filename(pkg)); + fpath = _alpm_filecache_find(pkg->handle, alpm_pkg_get_filename(pkg)); retval = _alpm_test_md5sum(fpath, alpm_pkg_get_md5sum(pkg)); if(retval == 0) { - return(0); - } else if (retval == 1) { - pm_errno = PM_ERR_PKG_INVALID; + return 0; + } else if(retval == 1) { + pkg->handle->pm_errno = PM_ERR_PKG_INVALID; retval = -1; } - return(retval); + return retval; } /* Default package accessor functions. These will get overridden by any @@ -92,8 +86,6 @@ int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg) * a lazy-load cache. However, the defaults will work just fine for fully- * populated package structures. */ static const char *_pkg_get_filename(pmpkg_t *pkg) { return pkg->filename; } -static const char *_pkg_get_name(pmpkg_t *pkg) { return pkg->name; } -static const char *_pkg_get_version(pmpkg_t *pkg) { return pkg->version; } static const char *_pkg_get_desc(pmpkg_t *pkg) { return pkg->desc; } static const char *_pkg_get_url(pmpkg_t *pkg) { return pkg->url; } static time_t _pkg_get_builddate(pmpkg_t *pkg) { return pkg->builddate; } @@ -117,17 +109,28 @@ static alpm_list_t *_pkg_get_deltas(pmpkg_t *pkg) { return pkg->deltas; } static alpm_list_t *_pkg_get_files(pmpkg_t *pkg) { return pkg->files; } static alpm_list_t *_pkg_get_backup(pmpkg_t *pkg) { return pkg->backup; } -static void *_pkg_changelog_open(pmpkg_t *pkg) { return NULL; } -static size_t _pkg_changelog_read(void *ptr, size_t size, const pmpkg_t *pkg, const void *fp) { return 0; } -static int _pkg_changelog_close(const pmpkg_t *pkg, void *fp) { return EOF; } +static void *_pkg_changelog_open(pmpkg_t UNUSED *pkg) +{ + return NULL; +} + +static size_t _pkg_changelog_read(void UNUSED *ptr, size_t UNUSED size, + const pmpkg_t UNUSED *pkg, const UNUSED void *fp) +{ + return 0; +} + +static int _pkg_changelog_close(const pmpkg_t UNUSED *pkg, + void UNUSED *fp) +{ + return EOF; +} /** The standard package operations struct. Get fields directly from the * struct itself with no abstraction layer or any type of lazy loading. */ struct pkg_operations default_pkg_ops = { .get_filename = _pkg_get_filename, - .get_name = _pkg_get_name, - .get_version = _pkg_get_version, .get_desc = _pkg_get_desc, .get_url = _pkg_get_url, .get_builddate = _pkg_get_builddate, @@ -161,131 +164,180 @@ struct pkg_operations default_pkg_ops = { * package, which depend on where the package was loaded from. */ const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_filename(pkg); } const char SYMEXPORT *alpm_pkg_get_name(pmpkg_t *pkg) { - return pkg->ops->get_name(pkg); + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; + return pkg->name; } const char SYMEXPORT *alpm_pkg_get_version(pmpkg_t *pkg) { - return pkg->ops->get_version(pkg); + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; + return pkg->version; } const char SYMEXPORT *alpm_pkg_get_desc(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_desc(pkg); } const char SYMEXPORT *alpm_pkg_get_url(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_url(pkg); } time_t SYMEXPORT alpm_pkg_get_builddate(pmpkg_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(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_installdate(pkg); } const char SYMEXPORT *alpm_pkg_get_packager(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_packager(pkg); } const char SYMEXPORT *alpm_pkg_get_md5sum(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_md5sum(pkg); } const char SYMEXPORT *alpm_pkg_get_arch(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_arch(pkg); } off_t SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_size(pkg); } off_t SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_isize(pkg); } pmpkgreason_t SYMEXPORT alpm_pkg_get_reason(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->get_reason(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_licenses(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_groups(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_depends(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_depends(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_optdepends(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_optdepends(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_conflicts(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_conflicts(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_provides(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_provides(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_replaces(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_replaces(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_deltas(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_files(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_files(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->get_backup(pkg); } pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg) { /* Sanity checks */ - ASSERT(pkg != NULL, return(NULL)); - ASSERT(pkg->origin != PKG_FROM_FILE, return(NULL)); + ASSERT(pkg != NULL, return NULL); + ASSERT(pkg->origin != PKG_FROM_FILE, return NULL); + pkg->handle->pm_errno = 0; - return(pkg->origin_data.db); + return pkg->origin_data.db; } /** Open a package changelog for reading. */ void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; return pkg->ops->changelog_open(pkg); } @@ -293,6 +345,8 @@ void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg) size_t SYMEXPORT alpm_pkg_changelog_read(void *ptr, size_t size, const pmpkg_t *pkg, const void *fp) { + ASSERT(pkg != NULL, return 0); + pkg->handle->pm_errno = 0; return pkg->ops->changelog_read(ptr, size, pkg, fp); } @@ -306,17 +360,23 @@ int SYMEXPORT alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp) /** Close a package changelog for reading. */ int SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->changelog_close(pkg, fp); } int SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) { + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; return pkg->ops->has_scriptlet(pkg); } static void find_requiredby(pmpkg_t *pkg, pmdb_t *db, alpm_list_t **reqs) { const alpm_list_t *i; + pkg->handle->pm_errno = 0; + for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { pmpkg_t *cachepkg = i->data; alpm_list_t *i; @@ -338,10 +398,12 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg) alpm_list_t *reqs = NULL; pmdb_t *db; + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; + if(pkg->origin == PKG_FROM_FILE) { /* The sane option; search locally for things that require this. */ - db = alpm_option_get_localdb(); - find_requiredby(pkg, db, &reqs); + find_requiredby(pkg, pkg->handle->db_local, &reqs); } else { /* We have a DB package. if it is a local package, then we should * only search the local DB; else search all known sync databases. */ @@ -349,14 +411,14 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg) if(db->is_local) { find_requiredby(pkg, db, &reqs); } else { - for(i = handle->dbs_sync; i; i = i->next) { + for(i = pkg->handle->dbs_sync; i; i = i->next) { db = i->data; find_requiredby(pkg, db, &reqs); } reqs = alpm_list_msort(reqs, alpm_list_count(reqs), _alpm_str_cmp); } } - return(reqs); + return reqs; } /** @} */ @@ -365,11 +427,9 @@ pmpkg_t *_alpm_pkg_new(void) { pmpkg_t* pkg; - ALPM_LOG_FUNC; + CALLOC(pkg, 1, sizeof(pmpkg_t), return NULL); - CALLOC(pkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); - - return(pkg); + return pkg; } pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) @@ -377,21 +437,19 @@ pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) pmpkg_t *newpkg; alpm_list_t *i; - ALPM_LOG_FUNC; - - CALLOC(newpkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(newpkg, 1, sizeof(pmpkg_t), goto cleanup); newpkg->name_hash = pkg->name_hash; - STRDUP(newpkg->filename, pkg->filename, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->name, pkg->name, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->version, pkg->version, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->desc, pkg->desc, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->url, pkg->url, RET_ERR(PM_ERR_MEMORY, newpkg)); + STRDUP(newpkg->filename, pkg->filename, goto cleanup); + STRDUP(newpkg->name, pkg->name, goto cleanup); + STRDUP(newpkg->version, pkg->version, goto cleanup); + STRDUP(newpkg->desc, pkg->desc, goto cleanup); + STRDUP(newpkg->url, pkg->url, goto cleanup); newpkg->builddate = pkg->builddate; newpkg->installdate = pkg->installdate; - STRDUP(newpkg->packager, pkg->packager, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->md5sum, pkg->md5sum, RET_ERR(PM_ERR_MEMORY, newpkg)); - STRDUP(newpkg->arch, pkg->arch, RET_ERR(PM_ERR_MEMORY, newpkg)); + STRDUP(newpkg->packager, pkg->packager, goto cleanup); + STRDUP(newpkg->md5sum, pkg->md5sum, goto cleanup); + STRDUP(newpkg->arch, pkg->arch, goto cleanup); newpkg->size = pkg->size; newpkg->isize = pkg->isize; newpkg->scriptlet = pkg->scriptlet; @@ -411,22 +469,25 @@ pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) newpkg->deltas = alpm_list_copy_data(pkg->deltas, sizeof(pmdelta_t)); /* internal */ + newpkg->infolevel = pkg->infolevel; newpkg->origin = pkg->origin; - newpkg->ops = pkg->ops; if(newpkg->origin == PKG_FROM_FILE) { newpkg->origin_data.file = strdup(pkg->origin_data.file); } else { newpkg->origin_data.db = pkg->origin_data.db; } - newpkg->infolevel = pkg->infolevel; + newpkg->ops = pkg->ops; + newpkg->handle = pkg->handle; - return(newpkg); + return newpkg; + +cleanup: + _alpm_pkg_free(newpkg); + return NULL; } void _alpm_pkg_free(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - if(pkg == NULL) { return; } @@ -438,6 +499,7 @@ void _alpm_pkg_free(pmpkg_t *pkg) FREE(pkg->url); FREE(pkg->packager); FREE(pkg->md5sum); + FREE(pkg->base64_sig); FREE(pkg->arch); FREELIST(pkg->licenses); FREELIST(pkg->replaces); @@ -467,8 +529,6 @@ void _alpm_pkg_free(pmpkg_t *pkg) */ void _alpm_pkg_free_trans(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - if(pkg == NULL) { return; } @@ -485,8 +545,6 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg) /* Is spkg an upgrade for localpkg? */ int _alpm_pkg_compare_versions(pmpkg_t *spkg, pmpkg_t *localpkg) { - ALPM_LOG_FUNC; - return alpm_pkg_vercmp(alpm_pkg_get_version(spkg), alpm_pkg_get_version(localpkg)); } @@ -497,7 +555,7 @@ int _alpm_pkg_cmp(const void *p1, const void *p2) { pmpkg_t *pkg1 = (pmpkg_t *)p1; pmpkg_t *pkg2 = (pmpkg_t *)p2; - return(strcoll(pkg1->name, pkg2->name)); + return strcoll(pkg1->name, pkg2->name); } /* Test for existence of a package in a alpm_list_t* @@ -508,10 +566,8 @@ pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) alpm_list_t *lp; unsigned long needle_hash; - ALPM_LOG_FUNC; - if(needle == NULL || haystack == NULL) { - return(NULL); + return NULL; } needle_hash = _alpm_hash_sdbm(needle); @@ -527,11 +583,11 @@ pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) /* finally: we had hash match, verify string match */ if(strcmp(info->name, needle) == 0) { - return(info); + return info; } } } - return(NULL); + return NULL; } /** Test if a package should be ignored. @@ -539,28 +595,29 @@ pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle) * Checks if the package is ignored via IgnorePkg, or if the package is * in a group ignored via IgnoreGrp. * + * @param handle the context handle * @param pkg the package to test * * @return 1 if the package should be ignored, 0 otherwise */ -int _alpm_pkg_should_ignore(pmpkg_t *pkg) +int _alpm_pkg_should_ignore(pmhandle_t *handle, pmpkg_t *pkg) { alpm_list_t *groups = NULL; /* first see if the package is ignored */ if(alpm_list_find_str(handle->ignorepkg, alpm_pkg_get_name(pkg))) { - return(1); + return 1; } /* next see if the package is in a group that is ignored */ for(groups = handle->ignoregrp; groups; groups = alpm_list_next(groups)) { char *grp = (char *)alpm_list_getdata(groups); if(alpm_list_find_str(alpm_pkg_get_groups(pkg), grp)) { - return(1); + return 1; } } - return(0); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index b161d5f1..bc5b2671 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -24,11 +24,14 @@ #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 "db.h" +#include "signing.h" typedef enum _pmpkgfrom_t { PKG_FROM_FILE = 1, @@ -45,8 +48,6 @@ typedef enum _pmpkgfrom_t { */ struct pkg_operations { const char *(*get_filename) (pmpkg_t *); - const char *(*get_name) (pmpkg_t *); - const char *(*get_version) (pmpkg_t *); const char *(*get_desc) (pmpkg_t *); const char *(*get_url) (pmpkg_t *); time_t (*get_builddate) (pmpkg_t *); @@ -96,6 +97,7 @@ struct __pmpkg_t { char *url; char *packager; char *md5sum; + char *base64_sig; char *arch; time_t builddate; @@ -108,6 +110,7 @@ struct __pmpkg_t { int scriptlet; pmpkgreason_t reason; + pmdbinfrq_t infolevel; pmpkgfrom_t origin; /* origin == PKG_FROM_FILE, use pkg->origin_data.file * origin == PKG_FROM_*DB, use pkg->origin_data.db */ @@ -115,7 +118,7 @@ struct __pmpkg_t { pmdb_t *db; char *file; } origin_data; - pmdbinfrq_t infolevel; + pmhandle_t *handle; alpm_list_t *licenses; alpm_list_t *replaces; @@ -137,10 +140,16 @@ pmpkg_t* _alpm_pkg_new(void); pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg); void _alpm_pkg_free(pmpkg_t *pkg); void _alpm_pkg_free_trans(pmpkg_t *pkg); + + +pmpkg_t *_alpm_pkg_load_internal(pmhandle_t *handle, const char *pkgfile, + int full, const char *md5sum, const char *base64_sig, + pgp_verify_t check_sig); + int _alpm_pkg_cmp(const void *p1, const void *p2); int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg); pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle); -int _alpm_pkg_should_ignore(pmpkg_t *pkg); +int _alpm_pkg_should_ignore(pmhandle_t *handle, pmpkg_t *pkg); #endif /* _ALPM_PACKAGE_H */ diff --git a/lib/libalpm/pkghash.c b/lib/libalpm/pkghash.c index 6dc43243..9e98fcd8 100644 --- a/lib/libalpm/pkghash.c +++ b/lib/libalpm/pkghash.c @@ -17,9 +17,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <errno.h> + #include "pkghash.h" #include "util.h" -#include "log.h" /* List of primes for possible sizes of hash tables. * @@ -55,11 +56,7 @@ pmpkghash_t *_alpm_pkghash_create(size_t size) pmpkghash_t *hash = NULL; size_t i, loopsize; - MALLOC(hash, sizeof(pmpkghash_t), RET_ERR(PM_ERR_MEMORY, NULL)); - - hash->list = NULL; - hash->entries = 0; - hash->buckets = 0; + CALLOC(hash, 1, sizeof(pmpkghash_t), return NULL); loopsize = sizeof(prime_list) / sizeof(*prime_list); for(i = 0; i < loopsize; i++) { @@ -70,15 +67,15 @@ pmpkghash_t *_alpm_pkghash_create(size_t size) } if(hash->buckets < size) { - _alpm_log(PM_LOG_ERROR, _("database larger than maximum size\n")); + errno = ERANGE; free(hash); - return(NULL); + return NULL; } - CALLOC(hash->hash_table, hash->buckets, sizeof(alpm_list_t*), \ - free(hash); RET_ERR(PM_ERR_MEMORY, NULL)); + CALLOC(hash->hash_table, hash->buckets, sizeof(alpm_list_t *), \ + free(hash); return NULL); - return(hash); + return hash; } static size_t get_hash_position(unsigned long name_hash, pmpkghash_t *hash) @@ -92,7 +89,7 @@ static size_t get_hash_position(unsigned long name_hash, pmpkghash_t *hash) position = (position + 1) % hash->buckets; } - return(position); + return position; } /* Expand the hash table size to the next increment and rebin the entries */ @@ -123,7 +120,7 @@ static pmpkghash_t *rehash(pmpkghash_t *oldhash) newhash = _alpm_pkghash_create(newsize); if(newhash == NULL) { /* creation of newhash failed, stick with old one... */ - return(oldhash); + return oldhash; } newhash->list = oldhash->list; @@ -144,7 +141,7 @@ static pmpkghash_t *rehash(pmpkghash_t *oldhash) _alpm_pkghash_free(oldhash); - return(newhash); + return newhash; } static pmpkghash_t *pkghash_add_pkg(pmpkghash_t *hash, pmpkg_t *pkg, int sorted) @@ -153,7 +150,7 @@ static pmpkghash_t *pkghash_add_pkg(pmpkghash_t *hash, pmpkg_t *pkg, int sorted) size_t position; if(pkg == NULL || hash == NULL) { - return(hash); + return hash; } if((hash->entries + 1) / MAX_HASH_LOAD > hash->buckets) { @@ -164,7 +161,7 @@ static pmpkghash_t *pkghash_add_pkg(pmpkghash_t *hash, pmpkg_t *pkg, int sorted) ptr = calloc(1, sizeof(alpm_list_t)); if(ptr == NULL) { - return(hash); + return hash; } ptr->data = pkg; @@ -179,17 +176,17 @@ static pmpkghash_t *pkghash_add_pkg(pmpkghash_t *hash, pmpkg_t *pkg, int sorted) } hash->entries += 1; - return(hash); + return hash; } pmpkghash_t *_alpm_pkghash_add(pmpkghash_t *hash, pmpkg_t *pkg) { - return(pkghash_add_pkg(hash, pkg, 0)); + return pkghash_add_pkg(hash, pkg, 0); } pmpkghash_t *_alpm_pkghash_add_sorted(pmpkghash_t *hash, pmpkg_t *pkg) { - return(pkghash_add_pkg(hash, pkg, 1)); + return pkghash_add_pkg(hash, pkg, 1); } static size_t move_one_entry(pmpkghash_t *hash, size_t start, size_t end) @@ -217,7 +214,7 @@ static size_t move_one_entry(pmpkghash_t *hash, size_t start, size_t end) * e.g. (47 + 0 - 1) % 47 == 46 */ end = (hash->buckets + end - 1) % hash->buckets; } - return(end); + return end; } /** @@ -240,7 +237,7 @@ pmpkghash_t *_alpm_pkghash_remove(pmpkghash_t *hash, pmpkg_t *pkg, } if(pkg == NULL || hash == NULL) { - return(hash); + return hash; } position = pkg->name_hash % hash->buckets; @@ -277,13 +274,13 @@ pmpkghash_t *_alpm_pkghash_remove(pmpkghash_t *hash, pmpkg_t *pkg, position = prev; } - return(hash); + return hash; } position = (position + 1) % hash->buckets; } - return(hash); + return hash; } void _alpm_pkghash_free(pmpkghash_t *hash) @@ -304,10 +301,8 @@ pmpkg_t *_alpm_pkghash_find(pmpkghash_t *hash, const char *name) unsigned long name_hash; size_t position; - ALPM_LOG_FUNC; - if(name == NULL || hash == NULL) { - return(NULL); + return NULL; } name_hash = _alpm_hash_sdbm(name); @@ -318,13 +313,13 @@ pmpkg_t *_alpm_pkghash_find(pmpkghash_t *hash, const char *name) pmpkg_t *info = lp->data; if(info->name_hash == name_hash && strcmp(info->name, name) == 0) { - return(info); + return info; } position = (position + 1) % hash->buckets; } - return(NULL); + return NULL; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 22ae2bb8..9f075016 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -26,8 +26,6 @@ #include <stdlib.h> #include <errno.h> -#include <time.h> -#include <fcntl.h> #include <string.h> #include <limits.h> #include <unistd.h> @@ -36,6 +34,7 @@ /* libalpm */ #include "remove.h" #include "alpm_list.h" +#include "alpm.h" #include "trans.h" #include "util.h" #include "log.h" @@ -44,65 +43,63 @@ #include "db.h" #include "deps.h" #include "handle.h" -#include "alpm.h" -int SYMEXPORT alpm_remove_pkg(pmpkg_t *pkg) +int SYMEXPORT alpm_remove_pkg(pmhandle_t *handle, pmpkg_t *pkg) { - pmtrans_t *trans; const char *pkgname; - - ALPM_LOG_FUNC; + pmtrans_t *trans; /* Sanity checks */ - ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(pkg != NULL, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); + ASSERT(handle == pkg->handle, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_INITIALIZED, - RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + RET_ERR(handle, PM_ERR_TRANS_NOT_INITIALIZED, -1)); - pkgname = alpm_pkg_get_name(pkg); + pkgname = pkg->name; if(_alpm_pkg_find(trans->remove, pkgname)) { - RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); + RET_ERR(handle, PM_ERR_TRANS_DUP_TARGET, -1); } - _alpm_log(PM_LOG_DEBUG, "adding %s in the target list\n", pkgname); + _alpm_log(handle, PM_LOG_DEBUG, "adding package %s to the transaction remove list\n", + pkgname); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(pkg)); - return(0); + return 0; } -static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db, - alpm_list_t *lp) +static void remove_prepare_cascade(pmhandle_t *handle, alpm_list_t *lp) { - ALPM_LOG_FUNC; + pmtrans_t *trans = handle->trans; while(lp) { alpm_list_t *i; for(i = lp; i; i = i->next) { pmdepmissing_t *miss = (pmdepmissing_t *)i->data; - pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target); + pmpkg_t *info = _alpm_db_get_pkgfromcache(handle->db_local, miss->target); if(info) { if(!_alpm_pkg_find(trans->remove, alpm_pkg_get_name(info))) { - _alpm_log(PM_LOG_DEBUG, "pulling %s in target list\n", + _alpm_log(handle, PM_LOG_DEBUG, "pulling %s in target list\n", alpm_pkg_get_name(info)); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info)); } } else { - _alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not find %s in database -- skipping\n"), miss->target); } } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); + lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), + trans->remove, NULL, 1); } } -static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, - alpm_list_t *lp) +static void remove_prepare_keep_needed(pmhandle_t *handle, alpm_list_t *lp) { - ALPM_LOG_FUNC; + pmtrans_t *trans = handle->trans; /* Remove needed packages (which break dependencies) from target list */ while(lp != NULL) { @@ -118,14 +115,15 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, &vpkg); pkg = vpkg; if(pkg) { - _alpm_log(PM_LOG_WARNING, _("removing %s from target list\n"), + _alpm_log(handle, PM_LOG_WARNING, _("removing %s from target list\n"), alpm_pkg_get_name(pkg)); _alpm_pkg_free(pkg); } } alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); + lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), + trans->remove, NULL, 1); } } @@ -133,37 +131,34 @@ static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db, * This functions takes a pointer to a alpm_list_t which will be * filled with a list of pmdepmissing_t* objects representing * the packages blocking the transaction. - * @param trans the transaction object - * @param db the database of local packages + * @param handle the context handle * @param data a pointer to an alpm_list_t* to fill */ -int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) +int _alpm_remove_prepare(pmhandle_t *handle, alpm_list_t **data) { alpm_list_t *lp; - - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + pmtrans_t *trans = handle->trans; + pmdb_t *db = handle->db_local; if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) { - _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); - _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); + _alpm_log(handle, PM_LOG_DEBUG, "finding removable dependencies\n"); + _alpm_recursedeps(db, trans->remove, + trans->flags & PM_TRANS_FLAG_RECURSEALL); } if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, trans->remove, NULL); + _alpm_log(handle, PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); + lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(db), trans->remove, NULL, 1); if(lp != NULL) { if(trans->flags & PM_TRANS_FLAG_CASCADE) { - remove_prepare_cascade(trans, db, lp); - } else if (trans->flags & PM_TRANS_FLAG_UNNEEDED) { + remove_prepare_cascade(handle, lp); + } else if(trans->flags & PM_TRANS_FLAG_UNNEEDED) { /* Remove needed packages (which would break dependencies) * from target list */ - remove_prepare_keep_needed(trans, db, lp); + remove_prepare_keep_needed(handle, lp); } else { if(data) { *data = lp; @@ -171,21 +166,21 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(lp); } - RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1); + RET_ERR(handle, PM_ERR_UNSATISFIED_DEPS, -1); } } } /* re-order w.r.t. dependencies */ - _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); - lp = _alpm_sortbydeps(trans->remove, 1); + _alpm_log(handle, PM_LOG_DEBUG, "sorting by dependencies\n"); + lp = _alpm_sortbydeps(handle, trans->remove, 1); /* free the old alltargs */ alpm_list_free(trans->remove); trans->remove = lp; /* -Rcs == -Rc then -Rs */ if((trans->flags & PM_TRANS_FLAG_CASCADE) && (trans->flags & PM_TRANS_FLAG_RECURSE)) { - _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n"); + _alpm_log(handle, PM_LOG_DEBUG, "finding removable dependencies\n"); _alpm_recursedeps(db, trans->remove, trans->flags & PM_TRANS_FLAG_RECURSEALL); } @@ -193,18 +188,19 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL); } - return(0); + return 0; } -static int can_remove_file(const char *path, alpm_list_t *skip) +static int can_remove_file(pmhandle_t *handle, const char *path, + alpm_list_t *skip_remove) { - char file[PATH_MAX+1]; + char file[PATH_MAX]; snprintf(file, PATH_MAX, "%s%s", handle->root, path); - if(alpm_list_find_str(skip, file)) { + if(alpm_list_find_str(skip_remove, file)) { /* return success because we will never actually remove this file */ - return(1); + return 1; } /* If we fail write permissions due to a read-only filesystem, abort. * Assume all other possible failures are covered somewhere else */ @@ -212,23 +208,22 @@ static int can_remove_file(const char *path, alpm_list_t *skip) if(errno != EACCES && errno != ETXTBSY && access(file, F_OK) == 0) { /* only return failure if the file ACTUALLY exists and we can't write to * it - ignore "chmod -w" simple permission failures */ - _alpm_log(PM_LOG_ERROR, _("cannot remove file '%s': %s\n"), - file, strerror(errno)); - return(0); + _alpm_log(handle, PM_LOG_ERROR, _("cannot remove file '%s': %s\n"), + file, strerror(errno)); + return 0; } } - return(1); + return 1; } /* Helper function for iterating through a package's file and deleting them * Used by _alpm_remove_commit. */ -static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, int nosave) +static void unlink_file(pmhandle_t *handle, pmpkg_t *info, const char *filename, + alpm_list_t *skip_remove, int nosave) { struct stat buf; - char file[PATH_MAX+1]; - - ALPM_LOG_FUNC; + char file[PATH_MAX]; snprintf(file, PATH_MAX, "%s%s", handle->root, filename); @@ -236,7 +231,7 @@ static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, * see the big comment block in db_find_fileconflicts() for an * explanation. */ if(alpm_list_find_str(skip_remove, filename)) { - _alpm_log(PM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n", + _alpm_log(handle, PM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n", file); return; } @@ -246,23 +241,23 @@ static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, * filesystem, we want to work with the linked directory instead of the * actual symlink */ if(lstat(file, &buf)) { - _alpm_log(PM_LOG_DEBUG, "file %s does not exist\n", file); + _alpm_log(handle, PM_LOG_DEBUG, "file %s does not exist\n", file); return; } if(S_ISDIR(buf.st_mode)) { if(rmdir(file)) { /* this is okay, other packages are probably using it (like /usr) */ - _alpm_log(PM_LOG_DEBUG, "keeping directory %s\n", file); + _alpm_log(handle, PM_LOG_DEBUG, "keeping directory %s\n", file); } else { - _alpm_log(PM_LOG_DEBUG, "removing directory %s\n", file); + _alpm_log(handle, PM_LOG_DEBUG, "removing directory %s\n", file); } } else { /* if the file needs backup and has been modified, back it up to .pacsave */ char *pkghash = _alpm_needbackup(filename, alpm_pkg_get_backup(info)); if(pkghash) { if(nosave) { - _alpm_log(PM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); + _alpm_log(handle, PM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); FREE(pkghash); } else { char *filehash = alpm_compute_md5sum(file); @@ -273,24 +268,24 @@ static void unlink_file(pmpkg_t *info, char *filename, alpm_list_t *skip_remove, char newpath[PATH_MAX]; snprintf(newpath, PATH_MAX, "%s.pacsave", file); rename(file, newpath); - _alpm_log(PM_LOG_WARNING, _("%s saved as %s\n"), file, newpath); - alpm_logaction("warning: %s saved as %s\n", file, newpath); + _alpm_log(handle, PM_LOG_WARNING, _("%s saved as %s\n"), file, newpath); + alpm_logaction(handle, "warning: %s saved as %s\n", file, newpath); return; } } } - _alpm_log(PM_LOG_DEBUG, "unlinking %s\n", file); + _alpm_log(handle, PM_LOG_DEBUG, "unlinking %s\n", file); if(unlink(file) == -1) { - _alpm_log(PM_LOG_ERROR, _("cannot remove file '%s': %s\n"), - filename, strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("cannot remove file '%s': %s\n"), + filename, strerror(errno)); } } } -int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, - pmtrans_t *trans) +int _alpm_upgraderemove_package(pmhandle_t *handle, + pmpkg_t *oldpkg, pmpkg_t *newpkg) { alpm_list_t *skip_remove, *b; alpm_list_t *newfiles, *lp; @@ -298,18 +293,16 @@ int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, alpm_list_t *files = alpm_pkg_get_files(oldpkg); const char *pkgname = alpm_pkg_get_name(oldpkg); - ALPM_LOG_FUNC; - - _alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)\n", + _alpm_log(handle, PM_LOG_DEBUG, "removing old package first (%s-%s)\n", oldpkg->name, oldpkg->version); - if(trans->flags & PM_TRANS_FLAG_DBONLY) { + if(handle->trans->flags & PM_TRANS_FLAG_DBONLY) { goto db; } /* copy the remove skiplist over */ skip_remove = alpm_list_join( - alpm_list_strdup(trans->skip_remove), + alpm_list_strdup(handle->trans->skip_remove), alpm_list_strdup(handle->noupgrade)); /* Add files in the NEW backup array to the skip_remove array * so this removal operation doesn't kill them */ @@ -322,83 +315,79 @@ int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, FREE(backup); continue; } - _alpm_log(PM_LOG_DEBUG, "adding %s to the skip_remove array\n", backup); + _alpm_log(handle, PM_LOG_DEBUG, "adding %s to the skip_remove array\n", backup); skip_remove = alpm_list_add(skip_remove, backup); } for(lp = files; lp; lp = lp->next) { - if(!can_remove_file(lp->data, skip_remove)) { - _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", + if(!can_remove_file(handle, lp->data, skip_remove)) { + _alpm_log(handle, PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", pkgname); - RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); + RET_ERR(handle, PM_ERR_PKG_CANT_REMOVE, -1); } } filenum = alpm_list_count(files); - _alpm_log(PM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); + _alpm_log(handle, PM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); /* iterate through the list backwards, unlinking files */ newfiles = alpm_list_reverse(files); for(lp = newfiles; lp; lp = alpm_list_next(lp)) { - unlink_file(oldpkg, lp->data, skip_remove, 0); + unlink_file(handle, oldpkg, lp->data, skip_remove, 0); } alpm_list_free(newfiles); FREELIST(skip_remove); db: /* remove the package from the database */ - _alpm_log(PM_LOG_DEBUG, "updating database\n"); - _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); + _alpm_log(handle, PM_LOG_DEBUG, "updating database\n"); + _alpm_log(handle, PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); if(_alpm_local_db_remove(handle->db_local, oldpkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), pkgname, alpm_pkg_get_version(oldpkg)); } /* remove the package from the cache */ if(_alpm_db_remove_pkgfromcache(handle->db_local, oldpkg) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), pkgname); } - return(0); + return 0; } -int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) +int _alpm_remove_packages(pmhandle_t *handle) { pmpkg_t *info; alpm_list_t *targ, *lp; size_t pkg_count; - - ALPM_LOG_FUNC; - - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + pmtrans_t *trans = handle->trans; pkg_count = alpm_list_count(trans->remove); for(targ = trans->remove; targ; targ = targ->next) { int position = 0; char scriptlet[PATH_MAX]; - info = (pmpkg_t*)targ->data; + info = (pmpkg_t *)targ->data; const char *pkgname = NULL; size_t targcount = alpm_list_count(targ); - if(handle->trans->state == STATE_INTERRUPTED) { - return(0); + if(trans->state == STATE_INTERRUPTED) { + return 0; } /* get the name now so we can use it after package is removed */ pkgname = alpm_pkg_get_name(info); snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", - _alpm_db_path(db), pkgname, alpm_pkg_get_version(info)); + _alpm_db_path(handle->db_local), pkgname, alpm_pkg_get_version(info)); EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL); - _alpm_log(PM_LOG_DEBUG, "removing package %s-%s\n", + _alpm_log(handle, PM_LOG_DEBUG, "removing package %s-%s\n", pkgname, alpm_pkg_get_version(info)); /* run the pre-remove scriptlet if it exists */ if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "pre_remove", - alpm_pkg_get_version(info), NULL, trans); + _alpm_runscriptlet(handle, scriptlet, "pre_remove", + alpm_pkg_get_version(info), NULL); } if(!(trans->flags & PM_TRANS_FLAG_DBONLY)) { @@ -407,15 +396,15 @@ int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) size_t filenum; for(lp = files; lp; lp = lp->next) { - if(!can_remove_file(lp->data, NULL)) { - _alpm_log(PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", + if(!can_remove_file(handle, lp->data, NULL)) { + _alpm_log(handle, PM_LOG_DEBUG, "not removing package '%s', can't remove all files\n", pkgname); - RET_ERR(PM_ERR_PKG_CANT_REMOVE, -1); + RET_ERR(handle, PM_ERR_PKG_CANT_REMOVE, -1); } } filenum = alpm_list_count(files); - _alpm_log(PM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); + _alpm_log(handle, PM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); /* init progress bar */ PROGRESS(trans, PM_TRANS_PROGRESS_REMOVE_START, info->name, 0, @@ -425,7 +414,7 @@ int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) newfiles = alpm_list_reverse(files); for(lp = newfiles; lp; lp = alpm_list_next(lp)) { int percent; - unlink_file(info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE); + unlink_file(handle, info, lp->data, NULL, trans->flags & PM_TRANS_FLAG_NOSAVE); /* update progress bar after each file */ percent = (position * 100) / filenum; @@ -442,20 +431,20 @@ int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) /* run the post-remove script if it exists */ if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) { - _alpm_runscriptlet(handle->root, scriptlet, "post_remove", - alpm_pkg_get_version(info), NULL, trans); + _alpm_runscriptlet(handle, scriptlet, "post_remove", + alpm_pkg_get_version(info), NULL); } /* remove the package from the database */ - _alpm_log(PM_LOG_DEBUG, "updating database\n"); - _alpm_log(PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); - if(_alpm_local_db_remove(db, info) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), + _alpm_log(handle, PM_LOG_DEBUG, "updating database\n"); + _alpm_log(handle, PM_LOG_DEBUG, "removing database entry '%s'\n", pkgname); + if(_alpm_local_db_remove(handle->db_local, info) == -1) { + _alpm_log(handle, PM_LOG_ERROR, _("could not remove database entry %s-%s\n"), pkgname, alpm_pkg_get_version(info)); } /* remove the package from the cache */ - if(_alpm_db_remove_pkgfromcache(db, info) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), + if(_alpm_db_remove_pkgfromcache(handle->db_local, info) == -1) { + _alpm_log(handle, PM_LOG_ERROR, _("could not remove entry '%s' from cache\n"), pkgname); } @@ -463,9 +452,9 @@ int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db) } /* run ldconfig if it exists */ - _alpm_ldconfig(handle->root); + _alpm_ldconfig(handle); - return(0); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h index a67e37a1..5cab526a 100644 --- a/lib/libalpm/remove.h +++ b/lib/libalpm/remove.h @@ -24,10 +24,11 @@ #include "alpm_list.h" #include "trans.h" -int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data); -int _alpm_remove_packages(pmtrans_t *trans, pmdb_t *db); +int _alpm_remove_prepare(pmhandle_t *handle, alpm_list_t **data); +int _alpm_remove_packages(pmhandle_t *handle); -int _alpm_upgraderemove_package(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans); +int _alpm_upgraderemove_package(pmhandle_t *handle, + pmpkg_t *oldpkg, pmpkg_t *newpkg); #endif /* _ALPM_REMOVE_H */ diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c new file mode 100644 index 00000000..ff97d4c7 --- /dev/null +++ b/lib/libalpm/signing.c @@ -0,0 +1,406 @@ +/* + * signing.c + * + * Copyright (c) 2008-2011 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#if HAVE_LIBGPGME +#include <locale.h> /* setlocale() */ +#include <gpgme.h> +#include "base64.h" +#endif + +/* libalpm */ +#include "signing.h" +#include "package.h" +#include "util.h" +#include "log.h" +#include "alpm.h" +#include "handle.h" + +#if HAVE_LIBGPGME +#define CHECK_ERR(void) do { \ + if(err != GPG_ERR_NO_ERROR) { goto error; } \ + } while(0) + +static const char *string_validity(gpgme_validity_t validity) +{ + switch(validity) { + case GPGME_VALIDITY_UNKNOWN: + return "unknown"; + case GPGME_VALIDITY_UNDEFINED: + return "undefined"; + case GPGME_VALIDITY_NEVER: + return "never"; + case GPGME_VALIDITY_MARGINAL: + return "marginal"; + case GPGME_VALIDITY_FULL: + return "full"; + case GPGME_VALIDITY_ULTIMATE: + return "ultimate"; + } + return "???"; +} + +static void sigsum_test_bit(gpgme_sigsum_t sigsum, alpm_list_t **summary, + gpgme_sigsum_t bit, const char *value) +{ + if(sigsum & bit) { + *summary = alpm_list_add(*summary, (void *)value); + } +} + +static alpm_list_t *list_sigsum(gpgme_sigsum_t sigsum) +{ + alpm_list_t *summary = NULL; + /* The docs say this can be a bitmask...not sure I believe it, but we'll code + * for it anyway and show all possible flags in the returned string. */ + + /* The signature is fully valid. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_VALID, "valid"); + /* The signature is good. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_GREEN, "green"); + /* The signature is bad. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_RED, "red"); + /* One key has been revoked. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_KEY_REVOKED, "key revoked"); + /* One key has expired. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_KEY_EXPIRED, "key expired"); + /* The signature has expired. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_SIG_EXPIRED, "sig expired"); + /* Can't verify: key missing. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_KEY_MISSING, "key missing"); + /* CRL not available. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_CRL_MISSING, "crl missing"); + /* Available CRL is too old. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_CRL_TOO_OLD, "crl too old"); + /* A policy was not met. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_BAD_POLICY, "bad policy"); + /* A system error occured. */ + sigsum_test_bit(sigsum, &summary, GPGME_SIGSUM_SYS_ERROR, "sys error"); + /* Fallback case */ + if(!sigsum) { + summary = alpm_list_add(summary, (void *)"(empty)"); + } + return summary; +} + +static int init_gpgme(pmhandle_t *handle) +{ + static int init = 0; + const char *version, *sigdir; + gpgme_error_t err; + gpgme_engine_info_t enginfo; + + if(init) { + /* we already successfully initialized the library */ + return 0; + } + + sigdir = alpm_option_get_signaturedir(handle); + if(!sigdir) { + RET_ERR(handle, PM_ERR_SIG_MISSINGDIR, 1); + } + + /* calling gpgme_check_version() returns the current version and runs + * some internal library setup code */ + version = gpgme_check_version(NULL); + _alpm_log(handle, PM_LOG_DEBUG, "GPGME version: %s\n", version); + gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL)); +#ifdef LC_MESSAGES + gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL)); +#endif + /* NOTE: + * The GPGME library installs a SIGPIPE signal handler automatically if + * the default signal hander is in use. The only time we set a handler + * for SIGPIPE is in dload.c, and we reset it when we are done. Given that + * we do this, we can let GPGME do its automagic. However, if we install + * a library-wide SIGPIPE handler, we will have to be careful. + */ + + /* check for OpenPGP support (should be a no-brainer, but be safe) */ + err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); + CHECK_ERR(); + + /* set and check engine information */ + err = gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, NULL, sigdir); + CHECK_ERR(); + err = gpgme_get_engine_info(&enginfo); + CHECK_ERR(); + _alpm_log(handle, PM_LOG_DEBUG, "GPGME engine info: file=%s, home=%s\n", + enginfo->file_name, enginfo->home_dir); + + init = 1; + return 0; + +error: + _alpm_log(handle, PM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err)); + RET_ERR(handle, PM_ERR_GPGME, 1); +} + +/** + * Decode a loaded signature in base64 form. + * @param base64_data the signature to attempt to decode + * @param data the decoded data; must be freed by the caller + * @param data_len the length of the returned data + * @return 0 on success, 1 on failure to properly decode + */ +static int decode_signature(const char *base64_data, + unsigned char **data, int *data_len) { + unsigned char *usline; + int len; + + len = strlen(base64_data); + usline = (unsigned char *)base64_data; + int ret, destlen = 0; + /* get the necessary size for the buffer by passing 0 */ + ret = base64_decode(NULL, &destlen, usline, len); + if(ret != 0 && ret != POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) { + goto error; + } + /* alloc our memory and repeat the call to decode */ + MALLOC(*data, (size_t)destlen, goto error); + ret = base64_decode(*data, &destlen, usline, len); + if(ret != 0) { + goto error; + } + *data_len = destlen; + return 0; + +error: + *data = NULL; + *data_len = 0; + return 1; +} + +/** + * Check the PGP signature for the given file path. + * If base64_sig is provided, it will be used as the signature data after + * decoding. If base64_sig is NULL, expect a signature file next to path + * (e.g. "%s.sig"). The return value will be 0 if all checked signatures are + * valid, 1 if there was some sort of problem (but not necessarily rejection), + * and -1 if an error occurred while checking signatures. If 1 is returned, + * pm_errno should be checked to see why the signatures did not pass muster. + * @param handle the context handle + * @param path the full path to a file + * @param base64_sig optional PGP signature data in base64 encoding + * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred) + */ +int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path, + const char *base64_sig) +{ + int ret = 0; + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_data_t filedata, sigdata; + gpgme_verify_result_t result; + gpgme_signature_t gpgsig; + char *sigpath = NULL; + unsigned char *decoded_sigdata = NULL; + FILE *file = NULL, *sigfile = NULL; + + if(!path || access(path, R_OK) != 0) { + RET_ERR(handle, PM_ERR_NOT_A_FILE, -1); + } + + if(!base64_sig) { + size_t len = strlen(path) + 5; + CALLOC(sigpath, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, -1)); + snprintf(sigpath, len, "%s.sig", path); + + if(!access(sigpath, R_OK) == 0) { + FREE(sigpath); + RET_ERR(handle, PM_ERR_SIG_UNKNOWN, -1); + } + } + + if(init_gpgme(handle)) { + /* pm_errno was set in gpgme_init() */ + return -1; + } + + _alpm_log(handle, PM_LOG_DEBUG, "checking signature for %s\n", path); + + memset(&ctx, 0, sizeof(ctx)); + memset(&sigdata, 0, sizeof(sigdata)); + memset(&filedata, 0, sizeof(filedata)); + + err = gpgme_new(&ctx); + CHECK_ERR(); + + /* create our necessary data objects to verify the signature */ + file = fopen(path, "rb"); + if(file == NULL) { + handle->pm_errno = PM_ERR_NOT_A_FILE; + ret = -1; + goto error; + } + err = gpgme_data_new_from_stream(&filedata, file); + CHECK_ERR(); + + /* next create data object for the signature */ + if(base64_sig) { + /* memory-based, we loaded it from a sync DB */ + int data_len; + int decode_ret = decode_signature(base64_sig, + &decoded_sigdata, &data_len); + if(decode_ret) { + ret = -1; + goto error; + } + err = gpgme_data_new_from_mem(&sigdata, + (char *)decoded_sigdata, data_len, 0); + } else { + /* file-based, it is on disk */ + sigfile = fopen(sigpath, "rb"); + if(sigfile == NULL) { + handle->pm_errno = PM_ERR_NOT_A_FILE; + ret = -1; + goto error; + } + err = gpgme_data_new_from_stream(&sigdata, sigfile); + } + CHECK_ERR(); + + /* here's where the magic happens */ + err = gpgme_op_verify(ctx, sigdata, filedata, NULL); + CHECK_ERR(); + result = gpgme_op_verify_result(ctx); + gpgsig = result->signatures; + if(!gpgsig) { + _alpm_log(handle, PM_LOG_DEBUG, "no signatures returned\n"); + ret = -1; + goto error; + } + + { + alpm_list_t *summary_list, *summary; + + _alpm_log(handle, PM_LOG_DEBUG, "fingerprint: %s\n", gpgsig->fpr); + summary_list = list_sigsum(gpgsig->summary); + for(summary = summary_list; summary; summary = summary->next) { + _alpm_log(handle, PM_LOG_DEBUG, "summary: %s\n", (const char *)summary->data); + } + alpm_list_free(summary_list); + _alpm_log(handle, PM_LOG_DEBUG, "status: %s\n", gpgme_strerror(gpgsig->status)); + _alpm_log(handle, PM_LOG_DEBUG, "timestamp: %lu\n", gpgsig->timestamp); + _alpm_log(handle, PM_LOG_DEBUG, "exp_timestamp: %lu\n", gpgsig->exp_timestamp); + _alpm_log(handle, PM_LOG_DEBUG, "validity: %s\n", + string_validity(gpgsig->validity)); + _alpm_log(handle, PM_LOG_DEBUG, "validity_reason: %s\n", + gpgme_strerror(gpgsig->validity_reason)); + _alpm_log(handle, PM_LOG_DEBUG, "pubkey algo: %s\n", + gpgme_pubkey_algo_name(gpgsig->pubkey_algo)); + _alpm_log(handle, PM_LOG_DEBUG, "hash algo: %s\n", + gpgme_hash_algo_name(gpgsig->hash_algo)); + } + + if(gpgsig->summary & GPGME_SIGSUM_VALID) { + /* good signature, continue */ + _alpm_log(handle, PM_LOG_DEBUG, _("File %s has a valid signature.\n"), + path); + } else if(gpgsig->summary & GPGME_SIGSUM_GREEN) { + /* 'green' signature, not sure what to do here */ + _alpm_log(handle, PM_LOG_WARNING, _("File %s has a green signature.\n"), + path); + } else if(gpgsig->summary & GPGME_SIGSUM_KEY_MISSING) { + handle->pm_errno = PM_ERR_SIG_UNKNOWN; + _alpm_log(handle, PM_LOG_WARNING, _("File %s has a signature from an unknown key.\n"), + path); + ret = -1; + } else { + /* we'll capture everything else here */ + handle->pm_errno = PM_ERR_SIG_INVALID; + _alpm_log(handle, PM_LOG_ERROR, _("File %s has an invalid signature.\n"), + path); + ret = 1; + } + +error: + gpgme_data_release(sigdata); + gpgme_data_release(filedata); + gpgme_release(ctx); + if(sigfile) { + fclose(sigfile); + } + if(file) { + fclose(file); + } + FREE(sigpath); + FREE(decoded_sigdata); + if(err != GPG_ERR_NO_ERROR) { + _alpm_log(handle, PM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err)); + RET_ERR(handle, PM_ERR_GPGME, -1); + } + return ret; +} +#else +int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path, + const char *base64_sig) +{ + return -1; +} +#endif + +/** + * Determines the necessity of checking for a valid PGP signature + * @param db the sync database to query + * + * @return signature verification level + */ +pgp_verify_t _alpm_db_get_sigverify_level(pmdb_t *db) +{ + if(db->pgp_verify != PM_PGP_VERIFY_UNKNOWN) { + return db->pgp_verify; + } else { + return alpm_option_get_default_sigverify(db->handle); + } +} + +/** + * Check the PGP signature for the given package file. + * @param pkg the package to check + * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred) + */ +int SYMEXPORT alpm_pkg_check_pgp_signature(pmpkg_t *pkg) +{ + ASSERT(pkg != NULL, return -1); + pkg->handle->pm_errno = 0; + + return _alpm_gpgme_checksig(pkg->handle, alpm_pkg_get_filename(pkg), + pkg->base64_sig); +} + +/** + * Check the PGP signature for the given database. + * @param db the database to check + * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred) + */ +int SYMEXPORT alpm_db_check_pgp_signature(pmdb_t *db) +{ + ASSERT(db != NULL, return -1); + db->handle->pm_errno = 0; + + return _alpm_gpgme_checksig(db->handle, _alpm_db_path(db), NULL); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h new file mode 100644 index 00000000..fdf81fcf --- /dev/null +++ b/lib/libalpm/signing.h @@ -0,0 +1,30 @@ +/* + * signing.h + * + * Copyright (c) 2008-2011 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef _ALPM_SIGNING_H +#define _ALPM_SIGNING_H + +#include "alpm.h" + +int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path, + const char *base64_sig); +pgp_verify_t _alpm_db_get_sigverify_level(pmdb_t *db); + +#endif /* _ALPM_SIGNING_H */ + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index f83b0ef9..05735730 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -26,11 +26,9 @@ #include <sys/types.h> /* off_t */ #include <stdlib.h> #include <stdio.h> -#include <fcntl.h> #include <string.h> #include <stdint.h> /* intmax_t */ #include <unistd.h> -#include <time.h> #include <limits.h> /* libalpm */ @@ -50,63 +48,61 @@ #include "delta.h" #include "remove.h" #include "diskspace.h" +#include "signing.h" /** Check for new version of pkg in sync repos * (only the first occurrence is considered in sync) */ pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync) { - ASSERT(pkg != NULL, return(NULL)); - alpm_list_t *i; pmpkg_t *spkg = NULL; + ASSERT(pkg != NULL, return NULL); + pkg->handle->pm_errno = 0; + for(i = dbs_sync; !spkg && i; i = i->next) { spkg = _alpm_db_get_pkgfromcache(i->data, alpm_pkg_get_name(pkg)); } if(spkg == NULL) { - _alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n", + _alpm_log(pkg->handle, PM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n", alpm_pkg_get_name(pkg)); - return(NULL); + return NULL; } /* compare versions and see if spkg is an upgrade */ if(_alpm_pkg_compare_versions(spkg, pkg) > 0) { - _alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", + _alpm_log(pkg->handle, PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg), alpm_pkg_get_version(spkg)); - return(spkg); + return spkg; } /* spkg is not an upgrade */ - return(NULL); + return NULL; } -/** Search for packages to upgrade and add them to the transaction. - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) +/** Search for packages to upgrade and add them to the transaction. */ +int SYMEXPORT alpm_sync_sysupgrade(pmhandle_t *handle, int enable_downgrade) { alpm_list_t *i, *j, *k; pmtrans_t *trans; pmdb_t *db_local; alpm_list_t *dbs_sync; - ALPM_LOG_FUNC; - - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; db_local = handle->db_local; dbs_sync = handle->dbs_sync; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, PM_ERR_TRANS_NOT_INITIALIZED, -1)); - _alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n"); + _alpm_log(handle, PM_LOG_DEBUG, "checking for package upgrades\n"); for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) { pmpkg_t *lpkg = i->data; if(_alpm_pkg_find(trans->add, lpkg->name)) { - _alpm_log(PM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); + _alpm_log(handle, PM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); continue; } @@ -116,46 +112,52 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) pmdb_t *sdb = j->data; /* Check sdb */ pmpkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); - if(spkg) { /* 1. literal was found in sdb */ + if(spkg) { + /* 1. literal was found in sdb */ int cmp = _alpm_pkg_compare_versions(spkg, lpkg); if(cmp > 0) { - _alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", + _alpm_log(handle, PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", lpkg->name, lpkg->version, spkg->version); /* check IgnorePkg/IgnoreGroup */ - if(_alpm_pkg_should_ignore(spkg) || _alpm_pkg_should_ignore(lpkg)) { - _alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), - lpkg->name, lpkg->version, spkg->version); + if(_alpm_pkg_should_ignore(handle, spkg) + || _alpm_pkg_should_ignore(handle, lpkg)) { + _alpm_log(handle, PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), + lpkg->name, lpkg->version, spkg->version); } else { - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", + _alpm_log(handle, PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else if(cmp < 0) { if(enable_downgrade) { /* check IgnorePkg/IgnoreGroup */ - if(_alpm_pkg_should_ignore(spkg) || _alpm_pkg_should_ignore(lpkg)) { - _alpm_log(PM_LOG_WARNING, _("%s: ignoring package downgrade (%s => %s)\n"), + if(_alpm_pkg_should_ignore(handle, spkg) + || _alpm_pkg_should_ignore(handle, lpkg)) { + _alpm_log(handle, PM_LOG_WARNING, _("%s: ignoring package downgrade (%s => %s)\n"), lpkg->name, lpkg->version, spkg->version); } else { - _alpm_log(PM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), + _alpm_log(handle, PM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), lpkg->name, lpkg->version, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else { - _alpm_log(PM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), + _alpm_log(handle, PM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), lpkg->name, lpkg->version, sdb->treename, spkg->version); } } - break; /* jump to next local package */ - } else { /* 2. search for replacers in sdb */ + /* jump to next local package */ + break; + } else { + /* 2. search for replacers in sdb */ int found = 0; for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { spkg = k->data; if(alpm_list_find_str(alpm_pkg_get_replaces(spkg), lpkg->name)) { found = 1; /* check IgnorePkg/IgnoreGroup */ - if(_alpm_pkg_should_ignore(spkg) || _alpm_pkg_should_ignore(lpkg)) { - _alpm_log(PM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), + if(_alpm_pkg_should_ignore(handle, spkg) + || _alpm_pkg_should_ignore(handle, lpkg)) { + _alpm_log(handle, PM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), lpkg->name, lpkg->version, spkg->name, spkg->version); continue; } @@ -172,22 +174,23 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { - _alpm_log(PM_LOG_WARNING, _("cannot replace %s by %s\n"), + _alpm_log(handle, PM_LOG_WARNING, _("cannot replace %s by %s\n"), lpkg->name, spkg->name); continue; } - _alpm_log(PM_LOG_DEBUG, "appending %s to the removes list of %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "appending %s to the removes list of %s\n", lpkg->name, tpkg->name); tpkg->removes = alpm_list_add(tpkg->removes, lpkg); /* check the to-be-replaced package's reason field */ if(alpm_pkg_get_reason(lpkg) == PM_PKG_REASON_EXPLICIT) { tpkg->reason = PM_PKG_REASON_EXPLICIT; } - } else { /* add spkg to the target list */ + } else { + /* add spkg to the target list */ /* copy over reason */ spkg->reason = alpm_pkg_get_reason(lpkg); spkg->removes = alpm_list_add(NULL, lpkg); - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", + _alpm_log(handle, PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } @@ -200,7 +203,7 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) } } - return(0); + return 0; } /** Find group members across a list of databases. @@ -228,10 +231,10 @@ alpm_list_t SYMEXPORT *alpm_find_grp_pkgs(alpm_list_t *dbs, if(_alpm_pkg_find(ignorelist, alpm_pkg_get_name(pkg))) { continue; } - if(_alpm_pkg_should_ignore(pkg)) { + if(_alpm_pkg_should_ignore(db->handle, pkg)) { ignorelist = alpm_list_add(ignorelist, pkg); int install = 0; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, + QUESTION(db->handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, NULL, NULL, &install); if(!install) continue; @@ -242,7 +245,7 @@ alpm_list_t SYMEXPORT *alpm_find_grp_pkgs(alpm_list_t *dbs, } } alpm_list_free(ignorelist); - return(pkgs); + return pkgs; } /** Compute the size of the files that will be downloaded to install a @@ -254,16 +257,17 @@ static int compute_download_size(pmpkg_t *newpkg) const char *fname; char *fpath; off_t size = 0; + pmhandle_t *handle = newpkg->handle; if(newpkg->origin != PKG_FROM_SYNCDB) { newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = 0; - return(0); + return 0; } fname = alpm_pkg_get_filename(newpkg); - ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); - fpath = _alpm_filecache_find(fname); + ASSERT(fname != NULL, RET_ERR(handle, PM_ERR_PKG_INVALID_NAME, -1)); + fpath = _alpm_filecache_find(handle, fname); if(fpath) { FREE(fpath); @@ -272,16 +276,16 @@ static int compute_download_size(pmpkg_t *newpkg) off_t dltsize; off_t pkgsize = alpm_pkg_get_size(newpkg); - dltsize = _alpm_shortest_delta_path( + dltsize = _alpm_shortest_delta_path(handle, alpm_pkg_get_deltas(newpkg), alpm_pkg_get_filename(newpkg), &newpkg->delta_path); if(newpkg->delta_path && (dltsize < pkgsize * MAX_DELTA_RATIO)) { - _alpm_log(PM_LOG_DEBUG, "using delta size\n"); + _alpm_log(handle, PM_LOG_DEBUG, "using delta size\n"); size = dltsize; } else { - _alpm_log(PM_LOG_DEBUG, "using package size\n"); + _alpm_log(handle, PM_LOG_DEBUG, "using package size\n"); size = alpm_pkg_get_size(newpkg); alpm_list_free(newpkg->delta_path); newpkg->delta_path = NULL; @@ -290,26 +294,22 @@ static int compute_download_size(pmpkg_t *newpkg) size = alpm_pkg_get_size(newpkg); } - _alpm_log(PM_LOG_DEBUG, "setting download size %jd for pkg %s\n", + _alpm_log(handle, PM_LOG_DEBUG, "setting download size %jd for pkg %s\n", (intmax_t)size, alpm_pkg_get_name(newpkg)); newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = size; - return(0); + return 0; } -int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data) +int _alpm_sync_prepare(pmhandle_t *handle, alpm_list_t **data) { + alpm_list_t *i, *j; alpm_list_t *deps = NULL; alpm_list_t *unresolvable = NULL; - alpm_list_t *i, *j; alpm_list_t *remove = NULL; int ret = 0; - - ALPM_LOG_FUNC; - - ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + pmtrans_t *trans = handle->trans; if(data) { *data = NULL; @@ -321,7 +321,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* Build up list by repeatedly resolving each transaction package */ /* Resolve targets dependencies */ EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n"); + _alpm_log(handle, PM_LOG_DEBUG, "resolving target's dependencies\n"); /* build remove list for resolvedeps */ for(i = trans->add; i; i = i->next) { @@ -333,14 +333,14 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* Compute the fake local database for resolvedeps (partial fix for the * phonon/qt issue) */ - alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(db_local), + alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local), trans->add, _alpm_pkg_cmp); /* Resolve packages in the transaction one at a time, in addition building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { pmpkg_t *pkg = i->data; - if(_alpm_resolvedeps(localpkgs, dbs_sync, pkg, trans->add, + if(_alpm_resolvedeps(handle, localpkgs, pkg, trans->add, &resolved, remove, data) == -1) { unresolvable = alpm_list_add(unresolvable, pkg); } @@ -353,14 +353,14 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync see if they'd like to ignore them rather than failing the sync */ if(unresolvable != NULL) { int remove_unresolvable = 0; - QUESTION(handle->trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable, + QUESTION(trans, PM_TRANS_CONV_REMOVE_PKGS, unresolvable, NULL, NULL, &remove_unresolvable); - if (remove_unresolvable) { + if(remove_unresolvable) { /* User wants to remove the unresolvable packages from the transaction. The packages will be removed from the actual transaction when the transaction packages are replaced with a dependency-reordered list below */ - pm_errno = 0; /* pm_errno was set by resolvedeps */ + handle->pm_errno = 0; /* pm_errno was set by resolvedeps */ if(data) { alpm_list_free_inner(*data, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(*data); @@ -388,7 +388,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* re-order w.r.t. dependencies */ alpm_list_free(trans->add); - trans->add = _alpm_sortbydeps(resolved, 0); + trans->add = _alpm_sortbydeps(handle, resolved, 0); alpm_list_free(resolved); EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL); @@ -398,11 +398,11 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* check for inter-conflicts and whatnot */ EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "looking for conflicts\n"); + _alpm_log(handle, PM_LOG_DEBUG, "looking for conflicts\n"); /* 1. check for conflicts in the target list */ - _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); - deps = _alpm_innerconflicts(trans->add); + _alpm_log(handle, PM_LOG_DEBUG, "check targets vs targets\n"); + deps = _alpm_innerconflicts(handle, trans->add); for(i = deps; i; i = i->next) { pmconflict_t *conflict = i->data; @@ -415,7 +415,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync continue; } - _alpm_log(PM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n", + _alpm_log(handle, PM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n", conflict->package1, conflict->package2); /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ @@ -428,8 +428,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync rsync = sync1; sync = sync2; } else { - _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); - pm_errno = PM_ERR_CONFLICTING_DEPS; + _alpm_log(handle, PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); + handle->pm_errno = PM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { pmconflict_t *newconflict = _alpm_conflict_dup(conflict); @@ -447,7 +447,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _alpm_dep_free(dep2); /* Prints warning */ - _alpm_log(PM_LOG_WARNING, + _alpm_log(handle, PM_LOG_WARNING, _("removing '%s' from target list because it conflicts with '%s'\n"), rsync->name, sync->name); trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL); @@ -460,8 +460,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync deps = NULL; /* 2. we check for target vs db conflicts (and resolve)*/ - _alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n"); - deps = _alpm_outerconflicts(db_local, trans->add); + _alpm_log(handle, PM_LOG_DEBUG, "check targets vs db and db vs targets\n"); + deps = _alpm_outerconflicts(handle->db_local, trans->add); for(i = deps; i; i = i->next) { pmconflict_t *conflict = i->data; @@ -479,21 +479,21 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync continue; } - _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", + _alpm_log(handle, PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n", conflict->package1, conflict->package2); pmpkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); - pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2); + pmpkg_t *local = _alpm_db_get_pkgfromcache(handle->db_local, conflict->package2); int doremove = 0; QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1, conflict->package2, conflict->reason, &doremove); if(doremove) { /* append to the removes list */ - _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); + _alpm_log(handle, PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); sync->removes = alpm_list_add(sync->removes, local); } else { /* abort */ - _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); - pm_errno = PM_ERR_CONFLICTING_DEPS; + _alpm_log(handle, PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); + handle->pm_errno = PM_ERR_CONFLICTING_DEPS; ret = -1; if(data) { pmconflict_t *newconflict = _alpm_conflict_dup(conflict); @@ -517,17 +517,18 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync for(j = spkg->removes; j; j = j->next) { pmpkg_t *rpkg = j->data; if(!_alpm_pkg_find(trans->remove, rpkg->name)) { - _alpm_log(PM_LOG_DEBUG, "adding '%s' to remove list\n", rpkg->name); + _alpm_log(handle, PM_LOG_DEBUG, "adding '%s' to remove list\n", rpkg->name); trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(rpkg)); } } } if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - _alpm_log(PM_LOG_DEBUG, "checking dependencies\n"); - deps = alpm_checkdeps(_alpm_db_get_pkgcache(db_local), 1, trans->remove, trans->add); + _alpm_log(handle, PM_LOG_DEBUG, "checking dependencies\n"); + deps = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local), + trans->remove, trans->add, 1); if(deps) { - pm_errno = PM_ERR_UNSATISFIED_DEPS; + handle->pm_errno = PM_ERR_UNSATISFIED_DEPS; ret = -1; if(data) { *data = deps; @@ -551,7 +552,7 @@ cleanup: alpm_list_free(unresolvable); alpm_list_free(remove); - return(ret); + return ret; } /** Returns the size of the files that will be downloaded to install a @@ -564,13 +565,13 @@ off_t SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg) if(!(newpkg->infolevel & INFRQ_DSIZE)) { compute_download_size(newpkg); } - return(newpkg->download_size); + return newpkg->download_size; } static int endswith(const char *filename, const char *extension) { const char *s = filename + strlen(filename) - strlen(extension); - return(strcmp(s, extension) == 0); + return strcmp(s, extension) == 0; } /** Applies delta files to create an upgraded package file. @@ -578,15 +579,16 @@ static int endswith(const char *filename, const char *extension) * All intermediate files are deleted, leaving only the starting and * ending package files. * - * @param trans the transaction + * @param handle the context handle * * @return 0 if all delta files were able to be applied, 1 otherwise. */ -static int apply_deltas(pmtrans_t *trans) +static int apply_deltas(pmhandle_t *handle) { alpm_list_t *i; int ret = 0; - const char *cachedir = _alpm_filecache_setup(); + const char *cachedir = _alpm_filecache_setup(handle); + pmtrans_t *trans = handle->trans; for(i = trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; @@ -603,18 +605,18 @@ static int apply_deltas(pmtrans_t *trans) char command[PATH_MAX]; size_t len = 0; - delta = _alpm_filecache_find(d->delta); + delta = _alpm_filecache_find(handle, d->delta); /* the initial package might be in a different cachedir */ if(dlts == delta_path) { - from = _alpm_filecache_find(d->from); + from = _alpm_filecache_find(handle, d->from); } else { /* len = cachedir len + from len + '/' + null */ len = strlen(cachedir) + strlen(d->from) + 2; - CALLOC(from, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1)); + CALLOC(from, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, 1)); snprintf(from, len, "%s/%s", cachedir, d->from); } len = strlen(cachedir) + strlen(d->to) + 2; - CALLOC(to, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1)); + CALLOC(to, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, 1)); snprintf(to, len, "%s/%s", cachedir, d->to); /* build the patch command */ @@ -625,7 +627,7 @@ static int apply_deltas(pmtrans_t *trans) snprintf(command, PATH_MAX, "xdelta3 -d -q -s %s %s %s", from, delta, to); } - _alpm_log(PM_LOG_DEBUG, "command: %s\n", command); + _alpm_log(handle, PM_LOG_DEBUG, "command: %s\n", command); EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, d->to, d->delta); @@ -650,13 +652,14 @@ static int apply_deltas(pmtrans_t *trans) if(retval != 0) { /* one delta failed for this package, cancel the remaining ones */ EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL); + handle->pm_errno = PM_ERR_DLT_PATCHFAILED; ret = 1; break; } } } - return(ret); + return ret; } /** Compares the md5sum of a file to the expected value. @@ -665,50 +668,75 @@ static int apply_deltas(pmtrans_t *trans) * should be deleted. * * @param trans the transaction - * @param filename the filename of the file to test + * @param filename the absolute path of the file to test * @param md5sum the expected md5sum of the file * * @return 0 if the md5sum matched, 1 if not, -1 in case of errors */ -static int test_md5sum(pmtrans_t *trans, const char *filename, +static int test_md5sum(pmtrans_t *trans, const char *filepath, const char *md5sum) { - char *filepath; - int ret; - - filepath = _alpm_filecache_find(filename); - - ret = _alpm_test_md5sum(filepath, md5sum); - + int ret = _alpm_test_md5sum(filepath, md5sum); if(ret == 1) { int doremove = 0; - QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)filename, + QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)filepath, NULL, NULL, &doremove); if(doremove) { unlink(filepath); } } - FREE(filepath); - - return(ret); + return ret; } -int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) +static int validate_deltas(pmhandle_t *handle, alpm_list_t *deltas, + alpm_list_t **data) { - alpm_list_t *i, *j, *files = NULL; - alpm_list_t *deltas = NULL; - size_t numtargs, current = 0, replaces = 0; - int errors = 0; - const char *cachedir = NULL; - int ret = -1; + int errors = 0, ret = 0; + alpm_list_t *i; + pmtrans_t *trans = handle->trans; - ALPM_LOG_FUNC; + if(!deltas) { + return 0; + } - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + /* Check integrity of deltas */ + EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL); - cachedir = _alpm_filecache_setup(); - trans->state = STATE_DOWNLOADING; + for(i = deltas; i; i = i->next) { + pmdelta_t *d = alpm_list_getdata(i); + const char *filename = alpm_delta_get_filename(d); + char *filepath = _alpm_filecache_find(handle, filename); + const char *md5sum = alpm_delta_get_md5sum(d); + + if(test_md5sum(trans, filepath, md5sum) != 0) { + errors++; + *data = alpm_list_add(*data, strdup(filename)); + } + FREE(filepath); + } + if(errors) { + handle->pm_errno = PM_ERR_DLT_INVALID; + return -1; + } + EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL); + + /* Use the deltas to generate the packages */ + EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL); + ret = apply_deltas(handle); + EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL); + return ret; +} + +static int download_files(pmhandle_t *handle, alpm_list_t **deltas) +{ + const char *cachedir; + alpm_list_t *i, *j; + alpm_list_t *files = NULL; + int errors = 0; + + cachedir = _alpm_filecache_setup(handle); + handle->trans->state = STATE_DOWNLOADING; /* Total progress - figure out the total download size if required to * pass to the callback. This function is called once, and it is up to the @@ -716,7 +744,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { off_t total_size = (off_t)0; /* sum up the download size for each package and store total */ - for(i = trans->add; i; i = i->next) { + for(i = handle->trans->add; i; i = i->next) { pmpkg_t *spkg = i->data; total_size += spkg->download_size; } @@ -727,59 +755,74 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) for(i = handle->dbs_sync; i; i = i->next) { pmdb_t *current = i->data; - for(j = trans->add; j; j = j->next) { + for(j = handle->trans->add; j; j = j->next) { pmpkg_t *spkg = j->data; if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { const char *fname = NULL; fname = alpm_pkg_get_filename(spkg); - ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); + ASSERT(fname != NULL, RET_ERR(handle, PM_ERR_PKG_INVALID_NAME, -1)); alpm_list_t *delta_path = spkg->delta_path; if(delta_path) { /* using deltas */ - alpm_list_t *dlts = NULL; - + alpm_list_t *dlts; for(dlts = delta_path; dlts; dlts = dlts->next) { - pmdelta_t *d = dlts->data; - - if(d->download_size != 0) { - /* add the delta filename to the download list if needed */ - files = alpm_list_add(files, strdup(d->delta)); + pmdelta_t *delta = dlts->data; + if(delta->download_size != 0) { + files = alpm_list_add(files, strdup(delta->delta)); } - /* keep a list of all the delta files for md5sums */ - deltas = alpm_list_add(deltas, d); + *deltas = alpm_list_add(*deltas, delta); } - } else { - /* not using deltas */ - if(spkg->download_size != 0) { - /* add the filename to the download list if needed */ - files = alpm_list_add(files, strdup(fname)); - } + } else if(spkg->download_size != 0) { + files = alpm_list_add(files, strdup(fname)); } } } if(files) { - EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); - errors = _alpm_download_files(files, current->servers, cachedir); + EVENT(handle->trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL); + for(j = files; j; j = j->next) { + const char *filename = j->data; + alpm_list_t *server; + int ret = -1; + for(server = current->servers; server; server = server->next) { + const char *server_url = server->data; + char *fileurl; + size_t len; + + /* print server + filename into a buffer */ + len = strlen(server_url) + strlen(filename) + 2; + CALLOC(fileurl, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, -1)); + snprintf(fileurl, len, "%s/%s", server_url, filename); + + ret = _alpm_download(handle, fileurl, cachedir, 0, 1, 0); + FREE(fileurl); + if(ret != -1) { + break; + } + } + if(ret == -1) { + errors++; + } + } - if (errors) { - _alpm_log(PM_LOG_WARNING, _("failed to retrieve some files from %s\n"), + FREELIST(files); + if(errors) { + _alpm_log(handle, PM_LOG_WARNING, _("failed to retrieve some files from %s\n"), current->treename); - if(pm_errno == 0) { - pm_errno = PM_ERR_RETRIEVE; + if(handle->pm_errno == 0) { + handle->pm_errno = PM_ERR_RETRIEVE; } - goto error; + return -1; } - FREELIST(files); } } - for(j = trans->add; j; j = j->next) { + for(j = handle->trans->add; j; j = j->next) { pmpkg_t *pkg = j->data; pkg->infolevel &= ~INFRQ_DSIZE; pkg->download_size = 0; @@ -789,70 +832,60 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->totaldlcb) { handle->totaldlcb(0); } + return 0; +} - /* if we have deltas to work with */ - if(handle->usedelta && deltas) { - int ret = 0; - errors = 0; - /* Check integrity of deltas */ - EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL); - - for(i = deltas; i; i = i->next) { - pmdelta_t *d = alpm_list_getdata(i); - const char *filename = alpm_delta_get_filename(d); - const char *md5sum = alpm_delta_get_md5sum(d); - - if(test_md5sum(trans, filename, md5sum) != 0) { - errors++; - *data = alpm_list_add(*data, strdup(filename)); - } - } - if(errors) { - pm_errno = PM_ERR_DLT_INVALID; - goto error; - } - EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL); +int _alpm_sync_commit(pmhandle_t *handle, alpm_list_t **data) +{ + alpm_list_t *i; + alpm_list_t *deltas = NULL; + size_t numtargs, current = 0, replaces = 0; + int errors; + pmtrans_t *trans = handle->trans; - /* Use the deltas to generate the packages */ - EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL); - ret = apply_deltas(trans); - EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL); + if(download_files(handle, &deltas)) { + alpm_list_free(deltas); + return -1; + } - if(ret) { - pm_errno = PM_ERR_DLT_PATCHFAILED; - goto error; - } + if(validate_deltas(handle, deltas, data)) { + alpm_list_free(deltas); + return -1; } + alpm_list_free(deltas); /* Check integrity of packages */ numtargs = alpm_list_count(trans->add); EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL); errors = 0; + for(i = trans->add; i; i = i->next, current++) { pmpkg_t *spkg = i->data; int percent = (current * 100) / numtargs; + const char *filename; + char *filepath; + pgp_verify_t check_sig; + + PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", percent, + numtargs, current); if(spkg->origin == PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } - PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", percent, - numtargs, current); - const char *filename = alpm_pkg_get_filename(spkg); - const char *md5sum = alpm_pkg_get_md5sum(spkg); + filename = alpm_pkg_get_filename(spkg); + filepath = _alpm_filecache_find(handle, filename); + pmdb_t *sdb = alpm_pkg_get_db(spkg); + check_sig = _alpm_db_get_sigverify_level(sdb); - if(test_md5sum(trans, filename, md5sum) != 0) { - errors++; - *data = alpm_list_add(*data, strdup(filename)); - continue; - } /* load the package file and replace pkgcache entry with it in the target list */ /* TODO: alpm_pkg_get_db() will not work on this target anymore */ - _alpm_log(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name); - char *filepath = _alpm_filecache_find(filename); - pmpkg_t *pkgfile; - if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) { - _alpm_pkg_free(pkgfile); + _alpm_log(handle, PM_LOG_DEBUG, + "replacing pkgcache entry with package file for target %s\n", + spkg->name); + pmpkg_t *pkgfile =_alpm_pkg_load_internal(handle, filepath, 1, spkg->md5sum, + spkg->base64_sig, check_sig); + if(!pkgfile) { errors++; *data = alpm_list_add(*data, strdup(filename)); FREE(filepath); @@ -863,17 +896,18 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) i->data = pkgfile; _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } + PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", 100, numtargs, current); EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); + + if(errors) { - pm_errno = PM_ERR_PKG_INVALID; - goto error; + RET_ERR(handle, PM_ERR_PKG_INVALID, -1); } if(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY) { - ret = 0; - goto error; + return 0; } trans->state = STATE_COMMITING; @@ -884,18 +918,17 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(!(trans->flags & PM_TRANS_FLAG_FORCE)) { EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans, - trans->add, trans->remove); + _alpm_log(handle, PM_LOG_DEBUG, "looking for file conflicts\n"); + alpm_list_t *conflict = _alpm_db_find_fileconflicts(handle, + trans->add, trans->remove); if(conflict) { - pm_errno = PM_ERR_FILE_CONFLICTS; if(data) { *data = conflict; } else { alpm_list_free_inner(conflict, (alpm_list_fn_free)_alpm_fileconflict_free); alpm_list_free(conflict); } - goto error; + RET_ERR(handle, PM_ERR_FILE_CONFLICTS, -1); } EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); @@ -905,10 +938,10 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) if(handle->checkspace) { EVENT(trans, PM_TRANS_EVT_DISKSPACE_START, NULL, NULL); - _alpm_log(PM_LOG_DEBUG, "checking available disk space\n"); - if(_alpm_check_diskspace(trans, handle->db_local) == -1) { - _alpm_log(PM_LOG_ERROR, "%s\n", _("not enough free disk space")); - goto error; + _alpm_log(handle, PM_LOG_DEBUG, "checking available disk space\n"); + if(_alpm_check_diskspace(handle) == -1) { + _alpm_log(handle, PM_LOG_ERROR, "%s\n", _("not enough free disk space")); + return -1; } EVENT(trans, PM_TRANS_EVT_DISKSPACE_DONE, NULL, NULL); @@ -916,26 +949,22 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) /* remove conflicting and to-be-replaced packages */ if(replaces) { - _alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); + _alpm_log(handle, PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); /* we want the frontend to be aware of commit details */ - if(_alpm_remove_packages(trans, handle->db_local) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not commit removal transaction\n")); - goto error; + if(_alpm_remove_packages(handle) == -1) { + _alpm_log(handle, PM_LOG_ERROR, _("could not commit removal transaction\n")); + return -1; } } /* install targets */ - _alpm_log(PM_LOG_DEBUG, "installing packages\n"); - if(_alpm_upgrade_packages(trans, handle->db_local) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not commit transaction\n")); - goto error; + _alpm_log(handle, PM_LOG_DEBUG, "installing packages\n"); + if(_alpm_upgrade_packages(handle) == -1) { + _alpm_log(handle, PM_LOG_ERROR, _("could not commit transaction\n")); + return -1; } - ret = 0; -error: - FREELIST(files); - alpm_list_free(deltas); - return(ret); + return 0; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h index 90a2d40d..3049dd21 100644 --- a/lib/libalpm/sync.h +++ b/lib/libalpm/sync.h @@ -24,8 +24,8 @@ #include "alpm.h" -int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data); -int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data); +int _alpm_sync_prepare(pmhandle_t *handle, alpm_list_t **data); +int _alpm_sync_commit(pmhandle_t *handle, alpm_list_t **data); #endif /* _ALPM_SYNC_H */ diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index bf9ef722..f0744937 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -28,8 +28,6 @@ #include <string.h> #include <unistd.h> #include <sys/types.h> -#include <sys/stat.h> -#include <sys/statvfs.h> #include <errno.h> #include <limits.h> #include <fcntl.h> @@ -41,11 +39,9 @@ #include "util.h" #include "log.h" #include "handle.h" -#include "add.h" #include "remove.h" #include "sync.h" #include "alpm.h" -#include "deps.h" /** \addtogroup alpm_trans Transaction Functions * @brief Functions to manipulate libalpm transactions @@ -68,22 +64,22 @@ static int make_lock(pmhandle_t *handle) } if(_alpm_makepath(dir)) { FREE(dir); - return(-1); + return -1; } FREE(dir); do { fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000); - } while (fd == -1 && errno == EINTR); + } while(fd == -1 && errno == EINTR); if(fd > 0) { FILE *f = fdopen(fd, "w"); fprintf(f, "%ld\n", (long)getpid()); fflush(f); fsync(fd); handle->lckstream = f; - return(0); + return 0; } - return(-1); + return -1; } /* Remove a lock file */ @@ -94,13 +90,13 @@ static int remove_lock(pmhandle_t *handle) handle->lckstream = NULL; } if(unlink(handle->lockfile) == -1 && errno != ENOENT) { - return(-1); + return -1; } - return(0); + return 0; } /** Initialize the transaction. */ -int SYMEXPORT alpm_trans_init(pmtransflag_t flags, +int SYMEXPORT alpm_trans_init(pmhandle_t *handle, pmtransflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress) { @@ -108,53 +104,47 @@ int SYMEXPORT alpm_trans_init(pmtransflag_t flags, const int required_db_version = 2; int db_version; - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, -1)); /* lock db */ if(!(flags & PM_TRANS_FLAG_NOLOCK)) { if(make_lock(handle)) { - RET_ERR(PM_ERR_HANDLE_LOCK, -1); + RET_ERR(handle, PM_ERR_HANDLE_LOCK, -1); } } - trans = _alpm_trans_new(); - if(trans == NULL) { - RET_ERR(PM_ERR_MEMORY, -1); - } - + CALLOC(trans, 1, sizeof(pmtrans_t), RET_ERR(handle, PM_ERR_MEMORY, -1)); trans->flags = flags; trans->cb_event = event; trans->cb_conv = conv; trans->cb_progress = progress; trans->state = STATE_INITIALIZED; - handle->trans = trans; - /* check database version */ db_version = _alpm_db_version(handle->db_local); if(db_version < required_db_version) { - _alpm_log(PM_LOG_ERROR, + _alpm_log(handle, PM_LOG_ERROR, _("%s database version is too old\n"), handle->db_local->treename); remove_lock(handle); _alpm_trans_free(trans); - RET_ERR(PM_ERR_DB_VERSION, -1); + RET_ERR(handle, PM_ERR_DB_VERSION, -1); } - return(0); + handle->trans = trans; + + return 0; } -static alpm_list_t *check_arch(alpm_list_t *pkgs) +static alpm_list_t *check_arch(pmhandle_t *handle, alpm_list_t *pkgs) { alpm_list_t *i; alpm_list_t *invalid = NULL; - const char *arch = alpm_option_get_arch(); + const char *arch = alpm_option_get_arch(handle); if(!arch) { - return(NULL); + return NULL; } for(i = pkgs; i; i = i->next) { pmpkg_t *pkg = i->data; @@ -164,134 +154,126 @@ static alpm_list_t *check_arch(alpm_list_t *pkgs) const char *pkgname = alpm_pkg_get_name(pkg); const char *pkgver = alpm_pkg_get_version(pkg); size_t len = strlen(pkgname) + strlen(pkgver) + strlen(pkgarch) + 3; - MALLOC(string, len, RET_ERR(PM_ERR_MEMORY, invalid)); + MALLOC(string, len, RET_ERR(handle, PM_ERR_MEMORY, invalid)); sprintf(string, "%s-%s-%s", pkgname, pkgver, pkgarch); invalid = alpm_list_add(invalid, string); } } - return(invalid); + return invalid; } /** Prepare a transaction. */ -int SYMEXPORT alpm_trans_prepare(alpm_list_t **data) +int SYMEXPORT alpm_trans_prepare(pmhandle_t *handle, alpm_list_t **data) { pmtrans_t *trans; - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(data != NULL, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1)); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, PM_ERR_TRANS_NOT_INITIALIZED, -1)); /* If there's nothing to do, return without complaining */ if(trans->add == NULL && trans->remove == NULL) { - return(0); + return 0; } - alpm_list_t *invalid = check_arch(trans->add); + alpm_list_t *invalid = check_arch(handle, trans->add); if(invalid) { if(data) { *data = invalid; } - RET_ERR(PM_ERR_PKG_INVALID_ARCH, -1); + RET_ERR(handle, PM_ERR_PKG_INVALID_ARCH, -1); } if(trans->add == NULL) { - if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) { + if(_alpm_remove_prepare(handle, data) == -1) { /* pm_errno is set by _alpm_remove_prepare() */ - return(-1); + return -1; } } else { - if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) { + if(_alpm_sync_prepare(handle, data) == -1) { /* pm_errno is set by _alpm_sync_prepare() */ - return(-1); + return -1; } } trans->state = STATE_PREPARED; - return(0); + return 0; } /** Commit a transaction. */ -int SYMEXPORT alpm_trans_commit(alpm_list_t **data) +int SYMEXPORT alpm_trans_commit(pmhandle_t *handle, alpm_list_t **data) { pmtrans_t *trans; - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1)); + ASSERT(trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state == STATE_PREPARED, RET_ERR(handle, PM_ERR_TRANS_NOT_PREPARED, -1)); - ASSERT(!(trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(PM_ERR_TRANS_NOT_LOCKED, -1)); + ASSERT(!(trans->flags & PM_TRANS_FLAG_NOLOCK), RET_ERR(handle, PM_ERR_TRANS_NOT_LOCKED, -1)); /* If there's nothing to do, return without complaining */ if(trans->add == NULL && trans->remove == NULL) { - return(0); + return 0; } trans->state = STATE_COMMITING; if(trans->add == NULL) { - if(_alpm_remove_packages(trans, handle->db_local) == -1) { + if(_alpm_remove_packages(handle) == -1) { /* pm_errno is set by _alpm_remove_commit() */ - return(-1); + return -1; } } else { - if(_alpm_sync_commit(trans, handle->db_local, data) == -1) { + if(_alpm_sync_commit(handle, data) == -1) { /* pm_errno is set by _alpm_sync_commit() */ - return(-1); + return -1; } } trans->state = STATE_COMMITED; - return(0); + return 0; } /** Interrupt a transaction. */ -int SYMEXPORT alpm_trans_interrupt(void) +int SYMEXPORT alpm_trans_interrupt(pmhandle_t *handle) { pmtrans_t *trans; - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_COMMITING || trans->state == STATE_INTERRUPTED, - RET_ERR(PM_ERR_TRANS_TYPE, -1)); + RET_ERR(handle, PM_ERR_TRANS_TYPE, -1)); trans->state = STATE_INTERRUPTED; - return(0); + return 0; } /** Release a transaction. */ -int SYMEXPORT alpm_trans_release(void) +int SYMEXPORT alpm_trans_release(pmhandle_t *handle) { pmtrans_t *trans; - ALPM_LOG_FUNC; - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + CHECK_HANDLE(handle, return -1); trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state != STATE_IDLE, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); + ASSERT(trans->state != STATE_IDLE, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); int nolock_flag = trans->flags & PM_TRANS_FLAG_NOLOCK; @@ -301,34 +283,20 @@ int SYMEXPORT alpm_trans_release(void) /* unlock db */ if(!nolock_flag) { if(remove_lock(handle)) { - _alpm_log(PM_LOG_WARNING, _("could not remove lock file %s\n"), - alpm_option_get_lockfile()); - alpm_logaction("warning: could not remove lock file %s\n", - alpm_option_get_lockfile()); + _alpm_log(handle, PM_LOG_WARNING, _("could not remove lock file %s\n"), + alpm_option_get_lockfile(handle)); + alpm_logaction(handle, "warning: could not remove lock file %s\n", + alpm_option_get_lockfile(handle)); } } - return(0); + return 0; } /** @} */ -pmtrans_t *_alpm_trans_new(void) -{ - pmtrans_t *trans; - - ALPM_LOG_FUNC; - - CALLOC(trans, 1, sizeof(pmtrans_t), RET_ERR(PM_ERR_MEMORY, NULL)); - trans->state = STATE_IDLE; - - return(trans); -} - void _alpm_trans_free(pmtrans_t *trans) { - ALPM_LOG_FUNC; - if(trans == NULL) { return; } @@ -351,7 +319,7 @@ static int grep(const char *fn, const char *needle) FILE *fp; if((fp = fopen(fn, "r")) == NULL) { - return(0); + return 0; } while(!feof(fp)) { char line[1024]; @@ -362,16 +330,15 @@ static int grep(const char *fn, const char *needle) * ends up being split across line reads */ if(strstr(line, needle)) { fclose(fp); - return(1); + return 1; } } fclose(fp); - return(0); + return 0; } -int _alpm_runscriptlet(const char *root, const char *installfn, - const char *script, const char *ver, - const char *oldver, pmtrans_t *trans) +int _alpm_runscriptlet(pmhandle_t *handle, const char *installfn, + const char *script, const char *ver, const char *oldver) { char scriptfn[PATH_MAX]; char cmdline[PATH_MAX]; @@ -381,23 +348,21 @@ int _alpm_runscriptlet(const char *root, const char *installfn, int clean_tmpdir = 0; int retval = 0; - ALPM_LOG_FUNC; - if(access(installfn, R_OK)) { /* not found */ - _alpm_log(PM_LOG_DEBUG, "scriptlet '%s' not found\n", installfn); - return(0); + _alpm_log(handle, PM_LOG_DEBUG, "scriptlet '%s' not found\n", installfn); + return 0; } /* creates a directory in $root/tmp/ for copying/extracting the scriptlet */ - snprintf(tmpdir, PATH_MAX, "%stmp/", root); + snprintf(tmpdir, PATH_MAX, "%stmp/", handle->root); if(access(tmpdir, F_OK) != 0) { _alpm_makepath_mode(tmpdir, 01777); } - snprintf(tmpdir, PATH_MAX, "%stmp/alpm_XXXXXX", root); + snprintf(tmpdir, PATH_MAX, "%stmp/alpm_XXXXXX", handle->root); if(mkdtemp(tmpdir) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not create temp directory\n")); - return(1); + _alpm_log(handle, PM_LOG_ERROR, _("could not create temp directory\n")); + return 1; } else { clean_tmpdir = 1; } @@ -405,12 +370,12 @@ int _alpm_runscriptlet(const char *root, const char *installfn, /* either extract or copy the scriptlet */ snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir); if(strcmp(script, "pre_upgrade") == 0 || strcmp(script, "pre_install") == 0) { - if(_alpm_unpack_single(installfn, tmpdir, ".INSTALL")) { + if(_alpm_unpack_single(handle, installfn, tmpdir, ".INSTALL")) { retval = 1; } } else { if(_alpm_copyfile(installfn, scriptfn)) { - _alpm_log(PM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), scriptfn, strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not copy tempfile to %s (%s)\n"), scriptfn, strerror(errno)); retval = 1; } } @@ -419,7 +384,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn, } /* chop off the root so we can find the tmpdir in the chroot */ - scriptpath = scriptfn + strlen(root) - 1; + scriptpath = scriptfn + strlen(handle->root) - 1; if(!grep(scriptfn, script)) { /* script not found in scriptlet file */ @@ -434,41 +399,41 @@ int _alpm_runscriptlet(const char *root, const char *installfn, scriptpath, script, ver); } - _alpm_log(PM_LOG_DEBUG, "executing \"%s\"\n", cmdline); + _alpm_log(handle, PM_LOG_DEBUG, "executing \"%s\"\n", cmdline); - retval = _alpm_run_chroot(root, "/bin/sh", argv); + retval = _alpm_run_chroot(handle, "/bin/sh", argv); cleanup: if(clean_tmpdir && _alpm_rmrf(tmpdir)) { - _alpm_log(PM_LOG_WARNING, _("could not remove tmpdir %s\n"), tmpdir); + _alpm_log(handle, PM_LOG_WARNING, _("could not remove tmpdir %s\n"), tmpdir); } - return(retval); + return retval; } -int SYMEXPORT alpm_trans_get_flags() +pmtransflag_t SYMEXPORT alpm_trans_get_flags(pmhandle_t *handle) { /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + CHECK_HANDLE(handle, return -1); + ASSERT(handle->trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, -1)); return handle->trans->flags; } -alpm_list_t SYMEXPORT * alpm_trans_get_add() +alpm_list_t SYMEXPORT *alpm_trans_get_add(pmhandle_t *handle) { /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(handle->trans != NULL, return(NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(handle->trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, NULL)); return handle->trans->add; } -alpm_list_t SYMEXPORT * alpm_trans_get_remove() +alpm_list_t SYMEXPORT *alpm_trans_get_remove(pmhandle_t *handle) { /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(handle->trans != NULL, return(NULL)); + CHECK_HANDLE(handle, return NULL); + ASSERT(handle->trans != NULL, RET_ERR(handle, PM_ERR_TRANS_NULL, NULL)); return handle->trans->remove; } diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 6702881b..e8587156 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -66,14 +66,12 @@ do { \ } \ } while(0) -pmtrans_t *_alpm_trans_new(void); void _alpm_trans_free(pmtrans_t *trans); int _alpm_trans_init(pmtrans_t *trans, pmtransflag_t flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress); -int _alpm_runscriptlet(const char *root, const char *installfn, - const char *script, const char *ver, - const char *oldver, pmtrans_t *trans); +int _alpm_runscriptlet(pmhandle_t *handle, const char *installfn, + const char *script, const char *ver, const char *oldver); #endif /* _ALPM_TRANS_H */ diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 430da92a..357ce506 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -53,10 +53,10 @@ /* libalpm */ #include "util.h" #include "log.h" -#include "package.h" #include "alpm.h" #include "alpm_list.h" #include "handle.h" +#include "trans.h" #ifndef HAVE_STRSEP /* This is a replacement for strsep which is not portable (missing on Solaris). @@ -65,14 +65,14 @@ char* strsep(char** str, const char* delims) { char* token; - if (*str==NULL) { + if(*str==NULL) { /* No more tokens */ return NULL; } token=*str; - while (**str!='\0') { - if (strchr(delims,**str)!=NULL) { + while(**str!='\0') { + if(strchr(delims,**str)!=NULL) { **str='\0'; (*str)++; return token; @@ -87,7 +87,7 @@ char* strsep(char** str, const char* delims) int _alpm_makepath(const char *path) { - return(_alpm_makepath_mode(path, 0755)); + return _alpm_makepath_mode(path, 0755); } /* does the same thing as 'mkdir -p' */ @@ -123,7 +123,7 @@ int _alpm_makepath_mode(const char *path, mode_t mode) free(orig); free(incr); umask(oldmask); - return(ret); + return ret; } #define CPBUFSIZE 8 * 1024 @@ -137,12 +137,12 @@ int _alpm_copyfile(const char *src, const char *dest) in = fopen(src, "rb"); if(in == NULL) { - return(1); + return 1; } out = fopen(dest, "wb"); if(out == NULL) { fclose(in); - return(1); + return 1; } CALLOC(buf, (size_t)CPBUFSIZE, (size_t)1, ret = 1; goto cleanup;); @@ -152,9 +152,6 @@ int _alpm_copyfile(const char *src, const char *dest) size_t nwritten = 0; nwritten = fwrite(buf, 1, len, out); if((nwritten != len) || ferror(out)) { - pm_errno = PM_ERR_WRITE; - _alpm_log(PM_LOG_ERROR, _("error writing to file '%s': %s\n"), - dest, strerror(errno)); ret = -1; goto cleanup; } @@ -175,7 +172,7 @@ cleanup: fclose(in); fclose(out); FREE(buf); - return(ret); + return ret; } /* Trim whitespace and newlines from a string @@ -186,7 +183,7 @@ char *_alpm_strtrim(char *str) if(*str == '\0') { /* string is empty, so we're done. */ - return(str); + return str; } while(isspace((unsigned char)*pch)) { @@ -198,7 +195,7 @@ char *_alpm_strtrim(char *str) /* check if there wasn't anything but whitespace in the string. */ if(*str == '\0') { - return(str); + return str; } pch = (str + (strlen(str) - 1)); @@ -207,7 +204,7 @@ char *_alpm_strtrim(char *str) } *++pch = '\0'; - return(str); + return str; } /* Compression functions */ @@ -215,36 +212,39 @@ char *_alpm_strtrim(char *str) /** * @brief Unpack a specific file in an archive. * - * @param archive the archive to unpack - * @param prefix where to extract the files - * @param fn a file within the archive to unpack + * @param handle the context handle + * @param archive the archive to unpack + * @param prefix where to extract the files + * @param filename a file within the archive to unpack * @return 0 on success, 1 on failure */ -int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn) +int _alpm_unpack_single(pmhandle_t *handle, const char *archive, + const char *prefix, const char *filename) { alpm_list_t *list = NULL; int ret = 0; - if(fn == NULL) { - return(1); + if(filename == NULL) { + return 1; } - list = alpm_list_add(list, (void *)fn); - ret = _alpm_unpack(archive, prefix, list, 1); + list = alpm_list_add(list, (void *)filename); + ret = _alpm_unpack(handle, archive, prefix, list, 1); alpm_list_free(list); - return(ret); + return ret; } /** * @brief Unpack a list of files in an archive. * - * @param archive 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 handle the context handle + * @param archive 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(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst) +int _alpm_unpack(pmhandle_t *handle, const char *archive, const char *prefix, + alpm_list_t *list, int breakfirst) { int ret = 0; mode_t oldmask; @@ -253,33 +253,33 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int char cwd[PATH_MAX]; int restore_cwd = 0; - ALPM_LOG_FUNC; - - if((_archive = archive_read_new()) == NULL) - RET_ERR(PM_ERR_LIBARCHIVE, 1); + if((_archive = archive_read_new()) == NULL) { + RET_ERR(handle, PM_ERR_LIBARCHIVE, 1); + } archive_read_support_compression_all(_archive); archive_read_support_format_all(_archive); if(archive_read_open_filename(_archive, archive, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), archive, + _alpm_log(handle, PM_LOG_ERROR, _("could not open file %s: %s\n"), archive, archive_error_string(_archive)); - RET_ERR(PM_ERR_PKG_OPEN, 1); + RET_ERR(handle, PM_ERR_PKG_OPEN, 1); } oldmask = umask(0022); /* save the cwd so we can restore it later */ if(getcwd(cwd, PATH_MAX) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); + _alpm_log(handle, PM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* just in case our cwd was removed in the upgrade operation */ if(chdir(prefix) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), prefix, strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + prefix, strerror(errno)); ret = 1; goto cleanup; } @@ -307,13 +307,13 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int char *found = alpm_list_find_str(list, prefix); free(prefix); if(!found) { - if (archive_read_data_skip(_archive) != ARCHIVE_OK) { + if(archive_read_data_skip(_archive) != ARCHIVE_OK) { ret = 1; goto cleanup; } continue; } else { - _alpm_log(PM_LOG_DEBUG, "extracting: %s\n", entryname); + _alpm_log(handle, PM_LOG_DEBUG, "extracting: %s\n", entryname); } } @@ -321,10 +321,10 @@ int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int int readret = archive_read_extract(_archive, entry, 0); if(readret == ARCHIVE_WARN) { /* operation succeeded but a non-critical error was encountered */ - _alpm_log(PM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), + _alpm_log(handle, PM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), entryname, archive_error_string(_archive)); } else if(readret != ARCHIVE_OK) { - _alpm_log(PM_LOG_ERROR, _("could not extract %s (%s)\n"), + _alpm_log(handle, PM_LOG_ERROR, _("could not extract %s (%s)\n"), entryname, archive_error_string(_archive)); ret = 1; goto cleanup; @@ -339,9 +339,10 @@ cleanup: umask(oldmask); archive_read_finish(_archive); if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + cwd, strerror(errno)); } - return(ret); + return ret; } /* does the same thing as 'rm -rf' */ @@ -356,18 +357,18 @@ int _alpm_rmrf(const char *path) if(_alpm_lstat(path, &st) == 0) { if(!S_ISDIR(st.st_mode)) { if(!unlink(path)) { - return(0); + return 0; } else { if(errno == ENOENT) { - return(0); + return 0; } else { - return(1); + return 1; } } } else { dirp = opendir(path); if(!dirp) { - return(1); + return 1; } for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { if(dp->d_ino) { @@ -382,16 +383,16 @@ int _alpm_rmrf(const char *path) errflag++; } } - return(errflag); + return errflag; } - return(0); + return 0; } -int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) +int _alpm_logaction(pmhandle_t *handle, const char *fmt, va_list args) { int ret = 0; - if(usesyslog) { + if(handle->usesyslog) { /* we can't use a va_list more than once, so we need to copy it * so we can use the original when calling vfprintf below. */ va_list args_syslog; @@ -400,7 +401,7 @@ int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) va_end(args_syslog); } - if(f) { + if(handle->logstream) { time_t t; struct tm *tm; @@ -408,17 +409,17 @@ int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args) tm = localtime(&t); /* Use ISO-8601 date format */ - fprintf(f, "[%04d-%02d-%02d %02d:%02d] ", + fprintf(handle->logstream, "[%04d-%02d-%02d %02d:%02d] ", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); - ret = vfprintf(f, fmt, args); - fflush(f); + ret = vfprintf(handle->logstream, fmt, args); + fflush(handle->logstream); } - return(ret); + return ret; } -int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) +int _alpm_run_chroot(pmhandle_t *handle, const char *path, char *const argv[]) { char cwd[PATH_MAX]; pid_t pid; @@ -426,28 +427,28 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) int restore_cwd = 0; int retval = 0; - ALPM_LOG_FUNC; - /* save the cwd so we can restore it later */ if(getcwd(cwd, PATH_MAX) == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n")); + _alpm_log(handle, PM_LOG_ERROR, _("could not get current working directory\n")); } else { restore_cwd = 1; } /* just in case our cwd was removed in the upgrade operation */ - if(chdir(root) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), root, strerror(errno)); + if(chdir(handle->root) != 0) { + _alpm_log(handle, PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + handle->root, strerror(errno)); goto cleanup; } - _alpm_log(PM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", path, root); + _alpm_log(handle, PM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n", + path, handle->root); /* Flush open fds before fork() to avoid cloning buffers */ fflush(NULL); if(pipe(pipefd) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -455,7 +456,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) /* fork- parent and child each have seperate code blocks below */ pid = fork(); if(pid == -1) { - _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)\n"), strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not fork a new process (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -470,7 +471,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) close(pipefd[1]); /* use fprintf instead of _alpm_log to send output through the parent */ - if(chroot(root) != 0) { + if(chroot(handle->root) != 0) { fprintf(stderr, _("could not change the root directory (%s)\n"), strerror(errno)); exit(1); } @@ -498,7 +499,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) char line[PATH_MAX]; if(fgets(line, PATH_MAX, pipe) == NULL) break; - alpm_logaction("%s", line); + alpm_logaction(handle, "%s", line); EVENT(handle->trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL); } fclose(pipe); @@ -506,7 +507,7 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) while(waitpid(pid, &status, 0) == -1) { if(errno != EINTR) { - _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("call to waitpid failed (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } @@ -514,14 +515,14 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) /* report error from above after the child has exited */ if(retval != 0) { - _alpm_log(PM_LOG_ERROR, _("could not open pipe (%s)\n"), strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not open pipe (%s)\n"), strerror(errno)); goto cleanup; } /* check the return status, make sure it is 0 (success) */ if(WIFEXITED(status)) { - _alpm_log(PM_LOG_DEBUG, "call to waitpid succeeded\n"); + _alpm_log(handle, PM_LOG_DEBUG, "call to waitpid succeeded\n"); if(WEXITSTATUS(status) != 0) { - _alpm_log(PM_LOG_ERROR, _("command failed to execute correctly\n")); + _alpm_log(handle, PM_LOG_ERROR, _("command failed to execute correctly\n")); retval = 1; } } @@ -529,42 +530,43 @@ int _alpm_run_chroot(const char *root, const char *path, char *const argv[]) cleanup: if(restore_cwd && chdir(cwd) != 0) { - _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); + _alpm_log(handle, PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); } - return(retval); + return retval; } -int _alpm_ldconfig(const char *root) +int _alpm_ldconfig(pmhandle_t *handle) { char line[PATH_MAX]; - _alpm_log(PM_LOG_DEBUG, "running ldconfig\n"); + _alpm_log(handle, PM_LOG_DEBUG, "running ldconfig\n"); - snprintf(line, PATH_MAX, "%setc/ld.so.conf", root); + snprintf(line, PATH_MAX, "%setc/ld.so.conf", handle->root); if(access(line, F_OK) == 0) { - snprintf(line, PATH_MAX, "%ssbin/ldconfig", root); + snprintf(line, PATH_MAX, "%ssbin/ldconfig", handle->root); if(access(line, X_OK) == 0) { char *argv[] = { "ldconfig", NULL }; - _alpm_run_chroot(root, "/sbin/ldconfig", argv); + _alpm_run_chroot(handle, "/sbin/ldconfig", argv); } } - return(0); + return 0; } /* Helper function for comparing strings using the * alpm "compare func" signature */ int _alpm_str_cmp(const void *s1, const void *s2) { - return(strcmp(s1, s2)); + return strcmp(s1, s2); } /** Find a filename in a registered alpm cachedir. + * @param handle the context handle * @param filename name of file to find * @return malloced path of file, NULL if not found */ -char *_alpm_filecache_find(const char* filename) +char *_alpm_filecache_find(pmhandle_t *handle, const char *filename) { char path[PATH_MAX]; char *retpath; @@ -572,52 +574,56 @@ char *_alpm_filecache_find(const char* filename) struct stat buf; /* Loop through the cache dirs until we find a matching file */ - for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { - snprintf(path, PATH_MAX, "%s%s", (char*)alpm_list_getdata(i), + for(i = alpm_option_get_cachedirs(handle); i; i = alpm_list_next(i)) { + snprintf(path, PATH_MAX, "%s%s", (char *)alpm_list_getdata(i), filename); if(stat(path, &buf) == 0 && S_ISREG(buf.st_mode)) { retpath = strdup(path); - _alpm_log(PM_LOG_DEBUG, "found cached pkg: %s\n", retpath); - return(retpath); + _alpm_log(handle, PM_LOG_DEBUG, "found cached pkg: %s\n", retpath); + return retpath; } } /* package wasn't found in any cachedir */ - RET_ERR(PM_ERR_PKG_NOT_FOUND, NULL); + return NULL; } /** Check the alpm cachedirs for existance and find a writable one. * If no valid cache directory can be found, use /tmp. + * @param handle the context handle * @return pointer to a writable cache directory. */ -const char *_alpm_filecache_setup(void) +const char *_alpm_filecache_setup(pmhandle_t *handle) { struct stat buf; alpm_list_t *i, *tmp; char *cachedir; /* Loop through the cache dirs until we find a writeable dir */ - for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + for(i = alpm_option_get_cachedirs(handle); i; i = alpm_list_next(i)) { cachedir = alpm_list_getdata(i); if(stat(cachedir, &buf) != 0) { /* cache directory does not exist.... try creating it */ - _alpm_log(PM_LOG_WARNING, _("no %s cache exists, creating...\n"), + _alpm_log(handle, PM_LOG_WARNING, _("no %s cache exists, creating...\n"), cachedir); if(_alpm_makepath(cachedir) == 0) { - _alpm_log(PM_LOG_DEBUG, "using cachedir: %s\n", cachedir); - return(cachedir); + _alpm_log(handle, PM_LOG_DEBUG, "using cachedir: %s\n", cachedir); + return cachedir; } } else if(S_ISDIR(buf.st_mode) && (buf.st_mode & S_IWUSR)) { - _alpm_log(PM_LOG_DEBUG, "using cachedir: %s\n", cachedir); - return(cachedir); + _alpm_log(handle, PM_LOG_DEBUG, "using cachedir: %s\n", cachedir); + return cachedir; + } else { + _alpm_log(handle, PM_LOG_DEBUG, "skipping cachedir: %s\n", cachedir); } } /* we didn't find a valid cache directory. use /tmp. */ - tmp = alpm_list_add(NULL, strdup("/tmp/")); - alpm_option_set_cachedirs(tmp); - _alpm_log(PM_LOG_DEBUG, "using cachedir: %s", "/tmp/\n"); - _alpm_log(PM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); - return(alpm_list_getdata(tmp)); + tmp = alpm_list_add(NULL, "/tmp/"); + alpm_option_set_cachedirs(handle, tmp); + alpm_list_free(tmp); + _alpm_log(handle, PM_LOG_DEBUG, "using cachedir: %s\n", "/tmp/"); + _alpm_log(handle, PM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); + return "/tmp/"; } /** lstat wrapper that treats /path/dirsymlink/ the same as /path/dirsymlink. @@ -630,18 +636,19 @@ const char *_alpm_filecache_setup(void) int _alpm_lstat(const char *path, struct stat *buf) { int ret; - char *newpath = strdup(path); - size_t len = strlen(newpath); + size_t len = strlen(path); /* strip the trailing slash if one exists */ - if(len != 0 && newpath[len - 1] == '/') { - newpath[len - 1] = '\0'; + if(len != 0 && path[len - 1] == '/') { + char *newpath = strdup(path); + newpath[len - 1] = '\0'; + ret = lstat(newpath, buf); + free(newpath); + } else { + ret = lstat(path, buf); } - ret = lstat(newpath, buf); - - FREE(newpath); - return(ret); + return ret; } #ifdef HAVE_LIBSSL @@ -652,11 +659,11 @@ static int md5_file(const char *path, unsigned char output[16]) MD5_CTX ctx; unsigned char *buf; - CALLOC(buf, 8192, sizeof(unsigned char), return(1)); + CALLOC(buf, 8192, sizeof(unsigned char), return 1); if((f = fopen(path, "rb")) == NULL) { free(buf); - return(1); + return 1; } MD5_Init(&ctx); @@ -672,11 +679,11 @@ static int md5_file(const char *path, unsigned char output[16]) if(ferror(f) != 0) { fclose(f); - return(2); + return 2; } fclose(f); - return(0); + return 0; } #endif @@ -691,17 +698,15 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename) char *md5sum; int ret, i; - ALPM_LOG_FUNC; - - ASSERT(filename != NULL, return(NULL)); + ASSERT(filename != NULL, return NULL); /* allocate 32 chars plus 1 for null */ md5sum = calloc(33, sizeof(char)); /* defined above for OpenSSL, otherwise defined in md5.h */ ret = md5_file(filename, output); - if (ret > 0) { - RET_ERR(PM_ERR_NOT_A_FILE, NULL); + if(ret > 0) { + return NULL; } /* Convert the result to something readable */ @@ -711,8 +716,7 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename) } md5sum[32] = '\0'; - _alpm_log(PM_LOG_DEBUG, "md5(%s) = %s\n", filename, md5sum); - return(md5sum); + return md5sum; } int _alpm_test_md5sum(const char *filepath, const char *md5sum) @@ -731,7 +735,7 @@ int _alpm_test_md5sum(const char *filepath, const char *md5sum) } FREE(md5sum2); - return(ret); + return ret; } /* Note: does NOT handle sparse files on purpose for speed. */ @@ -753,7 +757,7 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) } /* zero-copy - this is the entire next block of data. */ - b->ret = archive_read_data_block(a, (void*)&b->block, + b->ret = archive_read_data_block(a, (void *)&b->block, &b->block_size, &offset); b->block_offset = b->block; @@ -776,20 +780,19 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) /* allocate our buffer, or ensure our existing one is big enough */ if(!b->line) { /* set the initial buffer to the read block_size */ - CALLOC(b->line, b->block_size + 1, sizeof(char), - RET_ERR(PM_ERR_MEMORY, -1)); + CALLOC(b->line, b->block_size + 1, sizeof(char), return ENOMEM); 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); if(needed > b->max_line_size) { - RET_ERR(PM_ERR_MEMORY, -1); + return ERANGE; } if(needed > b->line_size) { /* need to realloc + copy data to fit total length */ char *new; - CALLOC(new, needed, sizeof(char), RET_ERR(PM_ERR_MEMORY, -1)); + CALLOC(new, needed, sizeof(char), return ENOMEM); memcpy(new, b->line, b->line_size); b->line_size = needed; b->line_offset = new + (b->line_offset - b->line); @@ -804,7 +807,7 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b) b->line_offset[len] = '\0'; b->block_offset = ++i; /* this is the main return point; from here you can read b->line */ - return(ARCHIVE_OK); + return ARCHIVE_OK; } else { /* we've looked through the whole block but no newline, copy it */ size_t len = (size_t)(b->block + b->block_size - b->block_offset); @@ -819,7 +822,7 @@ cleanup: int ret = b->ret; FREE(b->line); memset(b, 0, sizeof(b)); - return(ret); + return ret; } } @@ -833,12 +836,12 @@ int _alpm_splitname(const char *target, pmpkg_t *pkg) const char *version, *end; if(target == NULL || pkg == NULL) { - return(-1); + return -1; } end = target + strlen(target); /* remove any trailing '/' */ - while (*(end - 1) == '/') { + while(*(end - 1) == '/') { --end; } @@ -847,7 +850,7 @@ int _alpm_splitname(const char *target, pmpkg_t *pkg) for(version = end - 1; *version && *version != '-'; version--); for(version = version - 1; *version && *version != '-'; version--); if(*version != '-' || version == target) { - return(-1); + return -1; } /* copy into fields and return */ @@ -856,16 +859,15 @@ int _alpm_splitname(const char *target, pmpkg_t *pkg) } /* version actually points to the dash, so need to increment 1 and account * for potential end character */ - STRNDUP(pkg->version, version + 1, end - version - 1, - RET_ERR(PM_ERR_MEMORY, -1)); + STRNDUP(pkg->version, version + 1, end - version - 1, return -1); if(pkg->name) { FREE(pkg->name); } - STRNDUP(pkg->name, target, version - target, RET_ERR(PM_ERR_MEMORY, -1)); + STRNDUP(pkg->name, target, version - target, return -1); pkg->name_hash = _alpm_hash_sdbm(pkg->name); - return(0); + return 0; } /** @@ -880,13 +882,13 @@ unsigned long _alpm_hash_sdbm(const char *str) int c; if(!str) { - return(hash); + return hash; } while((c = *str++)) { hash = c + (hash << 6) + (hash << 16) - hash; } - return(hash); + return hash; } long _alpm_parsedate(const char *line) @@ -897,9 +899,9 @@ long _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 mktime(&tmp_tm); } - return(atol(line)); + return atol(line); } #ifndef HAVE_STRNDUP @@ -908,7 +910,7 @@ static size_t strnlen(const char *s, size_t max) { register const char *p; for(p = s; *p && max--; ++p); - return(p - s); + return (p - s); } char *strndup(const char *s, size_t n) @@ -916,11 +918,11 @@ char *strndup(const char *s, size_t n) size_t len = strnlen(s, n); char *new = (char *) malloc(len + 1); - if (new == NULL) + if(new == NULL) return NULL; new[len] = '\0'; - return (char *) memcpy(new, s, len); + return (char *)memcpy(new, s, len); } #endif diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index c66e9881..0549c81e 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -27,7 +27,9 @@ #include "config.h" #include "alpm_list.h" +#include "alpm.h" #include "package.h" /* pmpkg_t */ +#include "handle.h" /* pmhandle_t */ #include <stdio.h> #include <string.h> @@ -36,6 +38,8 @@ #include <time.h> #include <sys/stat.h> /* struct stat */ #include <archive.h> /* struct archive */ +#include <math.h> /* fabs */ +#include <float.h> /* DBL_EPSILON */ #ifdef ENABLE_NLS #include <libintl.h> /* here so it doesn't need to be included elsewhere */ @@ -45,7 +49,7 @@ #define _(s) s #endif -#define ALLOC_FAIL(s) do { _alpm_log(PM_LOG_ERROR, _("alloc failure: could not allocate %zd bytes\n"), s); } while(0) +#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) @@ -57,13 +61,17 @@ #define ASSERT(cond, action) do { if(!(cond)) { action; } } while(0) -#define RET_ERR_VOID(err) do { pm_errno = (err); \ - _alpm_log(PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerrorlast()); \ +#define RET_ERR_VOID(handle, err) do { (handle)->pm_errno = (err); \ + _alpm_log(handle, PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerror(err)); \ return; } while(0) -#define RET_ERR(err, ret) do { pm_errno = (err); \ - _alpm_log(PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerrorlast()); \ - return(ret); } while(0) +#define RET_ERR(handle, err, ret) do { (handle)->pm_errno = (err); \ + _alpm_log(handle, PM_LOG_DEBUG, "returning error %d from %s : %s\n", err, __func__, alpm_strerror(err)); \ + return (ret); } while(0) + +#define DOUBLE_EQ(x, y) (fabs((x) - (y)) < DBL_EPSILON) + +#define CHECK_HANDLE(handle, action) do { if(!(handle)) { action; } (handle)->pm_errno = 0; } while(0) /** * Used as a buffer/state holder for _alpm_archive_fgets(). @@ -85,15 +93,17 @@ 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); -int _alpm_unpack_single(const char *archive, const char *prefix, const char *fn); -int _alpm_unpack(const char *archive, const char *prefix, alpm_list_t *list, int breakfirst); +int _alpm_unpack_single(pmhandle_t *handle, const char *archive, + const char *prefix, const char *filename); +int _alpm_unpack(pmhandle_t *handle, const char *archive, const char *prefix, + alpm_list_t *list, int breakfirst); int _alpm_rmrf(const char *path); -int _alpm_logaction(int usesyslog, FILE *f, const char *fmt, va_list args); -int _alpm_run_chroot(const char *root, const char *path, char *const argv[]); -int _alpm_ldconfig(const char *root); +int _alpm_logaction(pmhandle_t *handle, const char *fmt, va_list args); +int _alpm_run_chroot(pmhandle_t *handle, const char *path, char *const argv[]); +int _alpm_ldconfig(pmhandle_t *handle); int _alpm_str_cmp(const void *s1, const void *s2); -char *_alpm_filecache_find(const char *filename); -const char *_alpm_filecache_setup(void); +char *_alpm_filecache_find(pmhandle_t *handle, const char *filename); +const char *_alpm_filecache_setup(pmhandle_t *handle); int _alpm_lstat(const char *path, struct stat *buf); int _alpm_test_md5sum(const char *filepath, const char *md5sum); int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b); @@ -113,6 +123,8 @@ char *strndup(const char *s, size_t n); #define SYMEXPORT __attribute__((visibility("default"))) #define SYMHIDDEN __attribute__((visibility("internal"))) +#define UNUSED __attribute__((unused)) + #endif /* _ALPM_UTIL_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c index eba66210..9f3a9b71 100644 --- a/lib/libalpm/version.c +++ b/lib/libalpm/version.c @@ -93,7 +93,7 @@ static int rpmvercmp(const char *a, const char *b) int ret = 0; /* easy comparison to see if versions are identical */ - if(strcmp(a, b) == 0) return(0); + if(strcmp(a, b) == 0) return 0; str1 = strdup(a); str2 = strdup(b); @@ -209,7 +209,7 @@ static int rpmvercmp(const char *a, const char *b) cleanup: free(str1); free(str2); - return(ret); + return ret; } /** Compare two version strings and determine which one is 'newer'. @@ -235,15 +235,15 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) /* ensure our strings are not null */ if(!a && !b) { - return(0); + return 0; } else if(!a) { - return(-1); + return -1; } else if(!b) { - return(1); + return 1; } /* another quick shortcut- if full version specs are equal */ if(strcmp(a, b) == 0) { - return(0); + return 0; } /* Parse both versions into [epoch:]version[-release] triplets. We probably @@ -266,7 +266,7 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) free(full1); free(full2); - return(ret); + return ret; } /* vim: set ts=2 sw=2 noet: */ diff --git a/m4/libcurl.m4 b/m4/libcurl.m4 new file mode 100644 index 00000000..01a0575c --- /dev/null +++ b/m4/libcurl.m4 @@ -0,0 +1,250 @@ +# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], +# [ACTION-IF-YES], [ACTION-IF-NO]) +# ---------------------------------------------------------- +# David Shaw <dshaw@jabberwocky.com> May-09-2006 +# +# Checks for libcurl. DEFAULT-ACTION is the string yes or no to +# specify whether to default to --with-libcurl or --without-libcurl. +# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the +# minimum version of libcurl to accept. Pass the version as a regular +# version number like 7.10.1. If not supplied, any version is +# accepted. ACTION-IF-YES is a list of shell commands to run if +# libcurl was successfully found and passed the various tests. +# ACTION-IF-NO is a list of shell commands that are run otherwise. +# Note that using --without-libcurl does run ACTION-IF-NO. +# +# This macro #defines HAVE_LIBCURL if a working libcurl setup is +# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary +# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are +# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy +# where yyy are the various protocols supported by libcurl. Both xxx +# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of +# the macro for the complete list of possible defines. Shell +# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also +# defined to 'yes' for those features and protocols that were found. +# Note that xxx and yyy keep the same capitalization as in the +# curl-config list (e.g. it's "HTTP" and not "http"). +# +# Users may override the detected values by doing something like: +# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure +# +# For the sake of sanity, this macro assumes that any libcurl that is +# found is after version 7.7.2, the first version that included the +# curl-config script. Note that it is very important for people +# packaging binary versions of libcurl to include this script! +# Without curl-config, we can only guess what protocols are available, +# or use curl_version_info to figure it out at runtime. + +AC_DEFUN([LIBCURL_CHECK_CONFIG], +[ + AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL]) + AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4]) + AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6]) + AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz]) + AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS]) + AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN]) + AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI]) + AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM]) + + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET]) + AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3]) + AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP]) + + AC_ARG_WITH(libcurl, + AC_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), + [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) + + if test "$_libcurl_with" != "no" ; then + + AC_PROG_AWK + + _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" + + _libcurl_try_link=yes + + if test -d "$_libcurl_with" ; then + LIBCURL_CPPFLAGS="-I$withval/include" + _libcurl_ldflags="-L$withval/lib" + AC_PATH_PROG([_libcurl_config],[curl-config],[], + ["$withval/bin"]) + else + AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH]) + fi + + if test x$_libcurl_config != "x" ; then + AC_CACHE_CHECK([for the version of libcurl], + [libcurl_cv_lib_curl_version], + [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) + + _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` + _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` + + if test $_libcurl_wanted -gt 0 ; then + AC_CACHE_CHECK([for libcurl >= version $2], + [libcurl_cv_lib_version_ok], + [ + if test $_libcurl_version -ge $_libcurl_wanted ; then + libcurl_cv_lib_version_ok=yes + else + libcurl_cv_lib_version_ok=no + fi + ]) + fi + + if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then + if test x"$LIBCURL_CPPFLAGS" = "x" ; then + LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` + fi + if test x"$LIBCURL" = "x" ; then + LIBCURL=`$_libcurl_config --libs` + + # This is so silly, but Apple actually has a bug in their + # curl-config script. Fixed in Tiger, but there are still + # lots of Panther installs around. + case "${host}" in + powerpc-apple-darwin7*) + LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` + ;; + esac + fi + + # All curl-config scripts support --feature + _libcurl_features=`$_libcurl_config --feature` + + # Is it modern enough to have --protocols? (7.12.4) + if test $_libcurl_version -ge 461828 ; then + _libcurl_protocols=`$_libcurl_config --protocols` + fi + else + _libcurl_try_link=no + fi + + unset _libcurl_wanted + fi + + if test $_libcurl_try_link = yes ; then + + # we didn't find curl-config, so let's see if the user-supplied + # link line (or failing that, "-lcurl") is enough. + LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} + + AC_CACHE_CHECK([whether libcurl is usable], + [libcurl_cv_lib_curl_usable], + [ + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBCURL $LIBS" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <curl/curl.h>],[ +/* Try and use a few common options to force a failure if we are + missing symbols or can't link. */ +int x; +curl_easy_setopt(NULL,CURLOPT_URL,NULL); +x=CURL_ERROR_SIZE; +x=CURLOPT_WRITEFUNCTION; +x=CURLOPT_FILE; +x=CURLOPT_ERRORBUFFER; +x=CURLOPT_STDERR; +x=CURLOPT_VERBOSE; +])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + ]) + + if test $libcurl_cv_lib_curl_usable = yes ; then + + # Does curl_free() exist in this version of libcurl? + # If not, fake it with free() + + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBS $LIBCURL" + + AC_CHECK_FUNC(curl_free,, + AC_DEFINE(curl_free,free, + [Define curl_free() as free() if our version of curl lacks curl_free.])) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + + AC_DEFINE(HAVE_LIBCURL,1, + [Define to 1 if you have a functional curl library.]) + AC_SUBST(LIBCURL_CPPFLAGS) + AC_SUBST(LIBCURL) + + for _libcurl_feature in $_libcurl_features ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1]) + eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes + done + + if test "x$_libcurl_protocols" = "x" ; then + + # We don't have --protocols, so just assume that all + # protocols are available + _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" + + if test x$libcurl_feature_SSL = xyes ; then + _libcurl_protocols="$_libcurl_protocols HTTPS" + + # FTPS wasn't standards-compliant until version + # 7.11.0 (0x070b00 == 461568) + if test $_libcurl_version -ge 461568; then + _libcurl_protocols="$_libcurl_protocols FTPS" + fi + fi + + # RTSP, IMAP, POP3 and SMTP were added in + # 7.20.0 (0x071400 == 463872) + if test $_libcurl_version -ge 463872; then + _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" + fi + fi + + for _libcurl_protocol in $_libcurl_protocols ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1]) + eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes + done + else + unset LIBCURL + unset LIBCURL_CPPFLAGS + fi + fi + + unset _libcurl_try_link + unset _libcurl_version_parse + unset _libcurl_config + unset _libcurl_feature + unset _libcurl_features + unset _libcurl_protocol + unset _libcurl_protocols + unset _libcurl_version + unset _libcurl_ldflags + fi + + if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then + # This is the IF-NO path + ifelse([$4],,:,[$4]) + else + # This is the IF-YES path + ifelse([$3],,:,[$3]) + fi + + unset _libcurl_with +])dnl diff --git a/scripts/.gitignore b/scripts/.gitignore index fe4616f2..927b14c8 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -5,3 +5,4 @@ rankmirrors repo-add repo-remove pkgdelta +pacman-key diff --git a/scripts/Makefile.am b/scripts/Makefile.am index ae6ce366..daa5b2ae 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -8,6 +8,7 @@ bin_SCRIPTS = \ OURSCRIPTS = \ makepkg \ pacman-db-upgrade \ + pacman-key \ pacman-optimize \ pkgdelta \ rankmirrors \ @@ -16,6 +17,7 @@ OURSCRIPTS = \ EXTRA_DIST = \ makepkg.sh.in \ pacman-db-upgrade.sh.in \ + pacman-key.sh.in \ pacman-optimize.sh.in \ pkgdelta.sh.in \ rankmirrors.sh.in \ @@ -45,7 +47,7 @@ edit = sed \ -e 's|@SIZECMD[@]|$(SIZECMD)|g' \ -e 's|@SEDINPLACE[@]|$(SEDINPLACE)|g' \ -e 's|@DUPATH[@]|$(DUPATH)|g' \ - -e 's|@configure_input[@]|Generated from $@.in; do not edit by hand.|g' + -e 's|@configure_input[@]|Generated from $@.sh.in; do not edit by hand.|g' ## 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 @@ -64,6 +66,7 @@ $(OURSCRIPTS): Makefile makepkg: $(srcdir)/makepkg.sh.in pacman-db-upgrade: $(srcdir)/pacman-db-upgrade.sh.in +pacman-key: $(srcdir)/pacman-key.sh.in pacman-optimize: $(srcdir)/pacman-optimize.sh.in pkgdelta: $(srcdir)/pkgdelta.sh.in rankmirrors: $(srcdir)/rankmirrors.sh.in diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 6fb36d27..9e0a667d 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -28,7 +28,7 @@ # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: # awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils), -# gettext, grep, gzip, openssl, sed, tput (ncurses), xz +# gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz # gettext initialization export TEXTDOMAIN='pacman' @@ -75,6 +75,7 @@ CHECKFUNC=0 PKGFUNC=0 SPLITPKG=0 PKGLIST=() +SIGNPKG='' # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call # when dealing with svn/cvs/etc PKGBUILDs. @@ -391,7 +392,7 @@ run_pacman() { local cmd printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@" if (( ! ASROOT )) && [[ ! $1 =~ ^-(T|Qq)$ ]]; then - if [ "$(type -p sudo)" ]; then + if type -p sudo >/dev/null; then cmd="sudo $cmd" else cmd="su root -c '$cmd'" @@ -855,7 +856,7 @@ tidy_install() { fi if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then - msg2 "$(gettext "Purging other files...")" + msg2 "$(gettext "Purging unwanted files...")" local pt for pt in "${PURGE_TARGETS[@]}"; do if [[ ${pt} = ${pt//\/} ]]; then @@ -931,6 +932,58 @@ tidy_install() { fi } +find_libdepends() { + local libdepends + find "$pkgdir" -type f -perm -u+x | while read filename + do + # get architecture of the file; if soarch is empty it's not an ELF binary + soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + [ -n "$soarch" ] || continue + # process all libraries needed by the binary + for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p') + do + # extract the library name: libfoo.so + soname="${sofile%%\.so\.*}.so" + # extract the major version: 1 + soversion="${sofile##*\.so\.}" + 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}") + fi + fi + done + done +} + +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}") + fi + fi + fi + done +} + write_pkginfo() { local builddate=$(date -u "+%s") if [[ -n $PACKAGER ]]; then @@ -960,13 +1013,44 @@ write_pkginfo() { [[ $license ]] && printf "license = %s\n" "${license[@]}" [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}" [[ $groups ]] && printf "group = %s\n" "${groups[@]}" - [[ $depends ]] && printf "depend = %s\n" "${depends[@]}" [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]}" [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}" - [[ $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}) + + for it in "${depends[@]}"; do + if [[ $it = *.so ]]; then + # check if the entry has been found by find_libdepends + # if not, it's unneeded; tell the user so he can remove it + if [[ ! $libdepends =~ (^|\s)${it}=.* ]]; then + error "$(gettext "Can't find library listed in \$depends: %s")" "$it" + 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 "Can't find library listed in \$provides: %s")" "$it" + return 1 + fi + else + echo "provides = $it" + fi + done + for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then @@ -1065,6 +1149,9 @@ create_package() { local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}" local ret=0 + [[ -f $pkg_file ]] && rm -f "$pkg_file" + [[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig" + # when fileglobbing, we want * in an empty directory to expand to # the null string rather than itself shopt -s nullglob @@ -1086,9 +1173,12 @@ create_package() { exit 1 # TODO: error code fi + create_signature "$pkg_file" + if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}" ret=$? + [[ -f $pkg_file.sig ]] && ln -sf "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig" fi if (( ret )); then @@ -1096,6 +1186,33 @@ create_package() { fi } +create_signature() { + if [[ $SIGNPKG != 'y' ]]; then + return + fi + local ret=0 + local filename="$1" + msg "$(gettext "Signing package...")" + if ! type -p gpg >/dev/null; then + error "$(gettext "Cannot find the gpg binary! Is gnupg installed?")" + exit 1 # $E_MISSING_PROGRAM + fi + + local SIGNWITHKEY="" + if [[ -n $GPGKEY ]]; then + SIGNWITHKEY="-u ${GPGKEY}" + fi + # The signature will be generated directly in ascii-friendly format + gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$? + + + if (( ! ret )); then + msg2 "$(gettext "Created signature file %s.")" "$filename.sig" + else + warning "$(gettext "Failed to sign package file.")" + fi +} + create_srcpackage() { cd "$startdir" @@ -1573,7 +1690,7 @@ usage() { echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")" echo "$(gettext " -f, --force Overwrite existing package")" echo "$(gettext " -g, --geninteg Generate integrity checks for source files")" - echo "$(gettext " -h, --help This help")" + echo "$(gettext " -h, --help Show this help message and exit")" echo "$(gettext " -i, --install Install package after successful build")" echo "$(gettext " -L, --log Log package build process")" echo "$(gettext " -m, --nocolor Disable colorized output messages")" @@ -1587,8 +1704,11 @@ usage() { printf "$(gettext " --check Run the check() function in the %s")\n" "$BUILDSCRIPT" printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" printf "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT" + echo "$(gettext " --key <key> Specify a key to use for gpg signing instead of the default")" printf "$(gettext " --nocheck Do not run the check() function in the %s")\n" "$BUILDSCRIPT" + echo "$(gettext " --nosign Do not create a signature for the package")" echo "$(gettext " --pkg <list> Only build listed packages from a split package")" + echo "$(gettext " --sign Sign the resulting package with gpg")" echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" echo @@ -1625,8 +1745,8 @@ ARGLIST=("$@") OPT_SHORT="AcCdefFghiLmop:rRsV" OPT_LONG="allsource,asroot,ignorearch,check,clean,cleancache,nodeps" OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver" -OPT_LONG+=",install,log,nocolor,nobuild,nocheck,pkg:,rmdeps" -OPT_LONG+=",repackage,skipinteg,source,syncdeps,version,config:" +OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps" +OPT_LONG+=",repackage,skipinteg,sign,source,syncdeps,version,config:" # Pacman Options OPT_LONG+=",noconfirm,noprogressbar" OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')" @@ -1660,15 +1780,18 @@ while true; do -g|--geninteg) GENINTEG=1 ;; --holdver) HOLDVER=1 ;; -i|--install) INSTALL=1 ;; + --key) shift; GPGKEY=$1 ;; -L|--log) LOGGING=1 ;; -m|--nocolor) USE_COLOR='n' ;; --nocheck) RUN_CHECK='n' ;; + --nosign) SIGNPKG='n' ;; -o|--nobuild) NOBUILD=1 ;; -p) shift; BUILDFILE=$1 ;; --pkg) shift; PKGLIST=($1) ;; -r|--rmdeps) RMDEPS=1 ;; -R|--repackage) REPKG=1 ;; --skipinteg) SKIPINTEG=1 ;; + --sign) SIGNPKG='y' ;; --source) SOURCEONLY=1 ;; -s|--syncdeps) DEP_BIN=1 ;; @@ -1685,6 +1808,9 @@ done [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST}) [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST}) [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST}) +[[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT} +[[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT} +[[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY} # default config is makepkg.conf MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} @@ -1748,6 +1874,9 @@ fi SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST} SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined +PKGEXT=${_PKGEXT:-$PKGEXT} +SRCEXT=${_SRCEXT:-$SRCEXT} +GPGKEY=${_GPGKEY:-$GPGKEY} if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then # The '\\0' is here to prevent gettext from thinking --holdver is an option @@ -1899,6 +2028,22 @@ if [[ -n "${PKGLIST[@]}" ]]; then pkgname=("${PKGLIST[@]}") fi +# check if gpg signature is to be created and if signing key is valid +if [[ -z "$SIGNPKG" && $(check_buildenv sign) == 'y' ]]; then + SIGNPKG='y' +fi +if [[ $SIGNPKG == 'y' ]]; then + if ! gpg --list-key ${GPGKEY} &>/dev/null; then + if [[ ! -z $GPGKEY ]]; then + error "$(gettext "The key ${GPGKEY} does not exist in your keyring.")" + else + error "$(gettext "There is no key in your keyring.")" + fi + exit 1 + fi +fi + + if (( ! SPLITPKG )); then fullver=$(get_full_version $epoch $pkgver $pkgrel) if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \ diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in new file mode 100644 index 00000000..20ec20fa --- /dev/null +++ b/scripts/pacman-key.sh.in @@ -0,0 +1,332 @@ +#!@BASH_SHELL@ -e +# +# pacman-key - manages pacman's keyring +# Based on apt-key, from Debian +# @configure_input@ +# +# Copyright (c) 2010-2011 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# gettext initialization +export TEXTDOMAIN='pacman' +export TEXTDOMAINDIR='@localedir@' + +myver="@PACKAGE_VERSION@" + +msg() { + local mesg=$1; shift + printf "==> ${mesg}\n" "$@" >&1 +} + +msg2() { + (( QUIET )) && return + local mesg=$1; shift + printf " -> ${mesg}\n" "$@" >&1 +} + +warning() { + local mesg=$1; shift + printf "==> $(gettext "WARNING:") ${mesg}\n" "$@" >&2 +} + +error() { + local mesg=$1; shift + printf "==> $(gettext "ERROR:") ${mesg}\n" "$@" >&2 +} + +usage() { + printf "pacman-key (pacman) %s\n" ${myver} + echo + printf "$(gettext "Usage: %s [options] <command> [arguments]")\n" $(basename $0) + echo + echo "$(gettext "Manage pacman's list of trusted keys")" + echo + echo "$(gettext "Options must be placed before commands. The available options are:")" + printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$CONFIG" + printf "$(gettext " --gpgdir Set an alternate directory for gnupg (instead of '%s')")\n" "$PACMAN_KEYRING_DIR" + echo + echo "$(gettext "The available commands are:")" + echo "$(gettext " -a, --add [<file(s)>] Add the specified keys (empty for stdin)")" + echo "$(gettext " -d, --del <keyid(s)> Remove the specified keyids")" + echo "$(gettext " -e, --export <keyid(s)> Export the specified keyids")" + echo "$(gettext " -f, --finger [<keyid(s)>] List fingerprint for specified or all keyids")" + echo "$(gettext " -h, --help Show this help message and exit")" + echo "$(gettext " -l, --list List keys")" + echo "$(gettext " -r, --receive <keyserver> <keyid(s)> Fetch the specified keyids")" + echo "$(gettext " -t, --trust <keyid(s)> Set the trust level of the given keyids")" + echo "$(gettext " -u, --updatedb Update the trustdb of pacman")" + echo "$(gettext " -V, --version Show program version")" + echo "$(gettext " --adv <params> Use pacman's keyring with advanced gpg commands")" + printf "$(gettext " --reload Reload the default keys")" + echo +} + +version() { + printf "pacman-key (pacman) %s\n" "${myver}" + printf "$(gettext "\ +Copyright (c) 2010-2011 Pacman Development Team <pacman-dev@archlinux.org>.\n\ +This is free software; see the source for copying conditions.\n\ +There is NO WARRANTY, to the extent permitted by law.\n")" +} + +# Read provided file and search for values matching the given key +# The contents of the file are expected to be in this format: key = value +# 'key', 'equal sign' and 'value' can be surrounded by random whitespace +# Usage: get_from "$file" "$key" # returns the value for the first matching key in the file +get_from() { + while read key _ value; do + if [[ $key = $2 ]]; then + echo "$value" + break + fi + done < "$1" +} + +reload_keyring() { + local PACMAN_SHARE_DIR='@prefix@/share/pacman' + local GPG_NOKEYRING="gpg --batch --quiet --ignore-time-conflict --no-options --no-default-keyring --homedir ${PACMAN_KEYRING_DIR}" + + # Variable used for iterating on keyrings + local key + local key_id + + # Keyring with keys to be added to the keyring + local ADDED_KEYS="${PACMAN_SHARE_DIR}/addedkeys.gpg" + + # Keyring with keys that were deprecated and will eventually be deleted + local DEPRECATED_KEYS="${PACMAN_SHARE_DIR}/deprecatedkeys.gpg" + + # List of keys removed from the keyring. This file is not a keyring, unlike the others. + # It is a textual list of values that gpg recogniezes as identifiers for keys. + local REMOVED_KEYS="${PACMAN_SHARE_DIR}/removedkeys" + + # Verify signatures of related files, if they exist + if [[ -r "${ADDED_KEYS}" ]]; then + msg "$(gettext "Verifying official keys file signature...")" + if ! ${GPG_PACMAN} --quiet --batch --verify "${ADDED_KEYS}.sig" 1>/dev/null; then + error "$(gettext "The signature of file %s is not valid.")" "${ADDED_KEYS}" + exit 1 + fi + fi + + if [[ -r "${DEPRECATED_KEYS}" ]]; then + msg "$(gettext "Verifying deprecated keys file signature...")" + if ! ${GPG_PACMAN} --quiet --batch --verify "${DEPRECATED_KEYS}.sig" 1>/dev/null; then + error "$(gettext "The signature of file %s is not valid.")" "${DEPRECATED_KEYS}" + exit 1 + fi + fi + + if [[ -r "${REMOVED_KEYS}" ]]; then + msg "$(gettext "Verifying deleted keys file signature...")" + if ! ${GPG_PACMAN} --quiet --batch --verify "${REMOVED_KEYS}.sig"; then + error "$(gettext "The signature of file %s is not valid.")" "${REMOVED_KEYS}" + exit 1 + fi + fi + + # Read the key ids to an array. The conversion from whatever is inside the file + # to key ids is important, because key ids are the only guarantee of identification + # for the keys. + local -A removed_ids + if [[ -r "${REMOVED_KEYS}" ]]; then + while read key; do + local key_values name + key_values=$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5,10 --output-delimiter=' ') + if [[ -n $key_values ]]; then + # The first word is the key_id + key_id=${key_values%% *} + # the rest if the name of the owner + name=${key_values#* } + if [[ -n ${key_id} ]]; then + # Mark this key to be deleted + removed_ids[$key_id]="$name" + fi + fi + done < "${REMOVED_KEYS}" + fi + + # List of keys that must be kept installed, even if in the list of keys to be removed + local HOLD_KEYS=$(get_from "$CONFIG" "HoldKeys") + + # Remove the keys that must be kept from the set of keys that should be removed + if [[ -n ${HOLD_KEYS} ]]; then + for key in ${HOLD_KEYS}; do + key_id=$(${GPG_PACMAN} --quiet --with-colons --list-key "${key}" | grep ^pub | cut -d: -f5) + if [[ -n "${removed_ids[$key_id]}" ]]; then + unset removed_ids[$key_id] + fi + done + fi + + # Add keys from the current set of keys from pacman-keyring package. The web of trust will + # be updated automatically. + if [[ -r "${ADDED_KEYS}" ]]; then + msg "$(gettext "Appending official keys...")" + local add_keys=$(${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5) + for key_id in ${add_keys}; do + # There is no point in adding a key that will be deleted right after + if [[ -z "${removed_ids[$key_id]}" ]]; then + ${GPG_NOKEYRING} --keyring "${ADDED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import + fi + done + fi + + if [[ -r "${DEPRECATED_KEYS}" ]]; then + msg "$(gettext "Appending deprecated keys...")" + local add_keys=$(${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --with-colons --list-keys | grep ^pub | cut -d: -f5) + for key_id in ${add_keys}; do + # There is no point in adding a key that will be deleted right after + if [[ -z "${removed_ids[$key_id]}" ]]; then + ${GPG_NOKEYRING} --keyring "${DEPRECATED_KEYS}" --export "${key_id}" | ${GPG_PACMAN} --import + fi + done + fi + + # Remove the keys not marked to keep + if (( ${#removed_ids[@]} > 0 )); then + msg "$(gettext "Removing deleted keys from keyring...")" + for key_id in "${!removed_ids[@]}"; do + echo " removing key $key_id - ${removed_ids[$key_id]}" + ${GPG_PACMAN} --quiet --batch --yes --delete-key "${key_id}" + done + fi + + # Update trustdb, just to be sure + msg "$(gettext "Updating trust database...")" + ${GPG_PACMAN} --batch --check-trustdb +} + +# PROGRAM START +if ! type gettext &>/dev/null; then + gettext() { + echo "$@" + } +fi + +if [[ $1 != "--version" && $1 != "-V" && $1 != "--help" && $1 != "-h" && $1 != "" ]]; then + if type -p gpg >/dev/null 2>&1 = 1; then + error "$(gettext "gnupg does not seem to be installed.")" + msg2 "$(gettext "pacman-key requires gnupg for most operations.")" + exit 1 + elif (( EUID != 0 )); then + error "$(gettext "pacman-key needs to be run as root.")" + exit 1 + fi +fi + +# Parse global options +CONFIG="@sysconfdir@/pacman.conf" +PACMAN_KEYRING_DIR="@sysconfdir@/pacman.d/gnupg" +while [[ $1 =~ ^--(config|gpgdir)$ ]]; do + case "$1" in + --config) shift; CONFIG="$1" ;; + --gpgdir) shift; PACMAN_KEYRING_DIR="$1" ;; + esac + shift +done + +if [[ ! -r "${CONFIG}" ]]; then + error "$(gettext "%s not found.")" "$CONFIG" + exit 1 +fi + +# Read GPGDIR from $CONFIG. +if [[ GPGDIR=$(get_from "$CONFIG" "GPGDir") == 0 ]]; then + PACMAN_KEYRING_DIR="${GPGDIR}" +fi +GPG_PACMAN="gpg --homedir ${PACMAN_KEYRING_DIR} --no-permission-warning" + +# Try to create $PACMAN_KEYRING_DIR if non-existent +# Check for simple existence rather than for a directory as someone may want +# to use a symlink here +[[ -e ${PACMAN_KEYRING_DIR} ]] || mkdir -p -m 755 "${PACMAN_KEYRING_DIR}" + +# Parse and execute command +command="$1" +if [[ -z "${command}" ]]; then + usage + exit 1 +fi +shift + +case "${command}" in + -a|--add) + # If there is no extra parameter, gpg will read stdin + ${GPG_PACMAN} --quiet --batch --import "$@" + ;; + -d|--del) + if (( $# == 0 )); then + error "$(gettext "You need to specify at least one key identifier")" + exit 1 + fi + ${GPG_PACMAN} --quiet --batch --delete-key --yes "$@" + ;; + -u|--updatedb) + ${GPG_PACMAN} --batch --check-trustdb + ;; + --reload) + reload_keyring + ;; + -l|--list) + ${GPG_PACMAN} --batch --list-sigs "$@" + ;; + -f|--finger) + ${GPG_PACMAN} --batch --fingerprint "$@" + ;; + -e|--export) + ${GPG_PACMAN} --armor --export "$@" + ;; + -r|--receive) + if (( $# < 2 )); then + error "$(gettext "You need to specify the keyserver and at least one key identifier")" + exit 1 + fi + keyserver="$1" + shift + ${GPG_PACMAN} --keyserver "${keyserver}" --recv-keys "$@" + ;; + -t|--trust) + if (( $# == 0 )); then + error "$(gettext "You need to specify at least one key identifier")" + exit 1 + fi + while (( $# > 0 )); do + # Verify if the key exists in pacman's keyring + if ${GPG_PACMAN} --list-keys "$1" > /dev/null 2>&1; then + ${GPG_PACMAN} --edit-key "$1" + else + error "$(gettext "The key identified by %s doesn't exist")" "$1" + exit 1 + fi + shift + done + ;; + --adv) + msg "$(gettext "Executing: %s ")$*" "${GPG_PACMAN}" + ${GPG_PACMAN} "$@" || ret=$? + exit $ret + ;; + -h|--help) + usage; exit 0 ;; + -V|--version) + version; exit 0 ;; + *) + error "$(gettext "Unknown command:") $command" + usage; exit 1 ;; +esac + +# vim: set ts=2 sw=2 noet: diff --git a/scripts/pkgdelta.sh.in b/scripts/pkgdelta.sh.in index ecca4277..d17b41d2 100644 --- a/scripts/pkgdelta.sh.in +++ b/scripts/pkgdelta.sh.in @@ -163,3 +163,5 @@ if ! type xdelta3 &>/dev/null; then fi create_xdelta "$1" "$2" + +# vim: set ts=2 sw=2 noet: diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index 02ab389c..0ffc0df5 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -4,8 +4,7 @@ # repo-remove - remove a package entry from a given repo database file # @configure_input@ # -# Copyright (c) 2006-2008 Aaron Griffin <aaron@archlinux.org> -# Copyright (c) 2007-2008 Dan McGee <dan@archlinux.org> +# Copyright (c) 2006-2011 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 @@ -30,6 +29,8 @@ confdir='@sysconfdir@' QUIET=0 DELTA=0 WITHFILES=0 +SIGN=0 +VERIFY=0 REPO_DB_FILE= LOCKFILE= CLEAN_LOCK=0 @@ -61,34 +62,42 @@ error() { # print usage instructions usage() { - printf "repo-add, repo-remove (pacman) %s\n\n" "$myver" - printf "$(gettext "Usage: repo-add [-d] [-f] [-q] <path-to-db> <package|delta> ...\n")" - printf "$(gettext "Usage: repo-remove [-q] <path-to-db> <packagename|delta> ...\n\n")" - printf "$(gettext "\ + cmd="$(basename $0)" + printf "%s (pacman) %s\n\n" "$cmd" "$myver" + if [[ $cmd == "repo-add" ]] ; then + printf "$(gettext "Usage: repo-add [options] <path-to-db> <package|delta> ...\n")" + printf "$(gettext "\ repo-add will update a package database by reading a package file.\n\ Multiple packages to add can be specified on the command line.\n\n")" - printf "$(gettext "\ + printf "$(gettext "Options:\n")" + printf "$(gettext " -d, --delta generate and add delta for package update\n")" + printf "$(gettext " -f, --files update database's file list\n")" + elif [[ $cmd == "repo-remove" ]] ; then + printf "$(gettext "Usage: repo-remove [options] <path-to-db> <packagename|delta> ...\n\n")" + printf "$(gettext "\ repo-remove will update a package database by removing the package name\n\ specified on the command line from the given repo database. Multiple\n\ packages to remove can be specified on the command line.\n\n")" - printf "$(gettext "\ -Use the -q/--quiet flag to minimize output to basic messages, warnings,\n\ -and errors.\n\n")" - printf "$(gettext "\ -Use the -d/--delta flag to automatically generate and add a delta file\n\ -between the old entry and the new one, if the old package file is found\n\ -next to the new one.\n\n")" - printf "$(gettext "\ -Use the -f/--files flag to update a database including file entries.\n\n")" - echo "$(gettext "Example: repo-add /path/to/repo.db.tar.gz pacman-3.0.0.pkg.tar.gz")" - echo "$(gettext "Example: repo-remove /path/to/repo.db.tar.gz kernel26")" + printf "$(gettext "Options:\n")" + fi + printf "$(gettext " -q, --quiet minimize output\n")" + printf "$(gettext " -s, --sign sign database with GnuPG after update\n")" + printf "$(gettext " -k, --key <key> use the specified key to sign the database\n")" + printf "$(gettext " -v, --verify verify database's signature before update\n")" + printf "$(gettext "\n\ +See %s(8) for more details and descriptions of the available options.\n\n")" $cmd + if [[ $cmd == "repo-add" ]] ; then + echo "$(gettext "Example: repo-add /path/to/repo.db.tar.gz pacman-3.0.0-1-i686.pkg.tar.gz")" + elif [[ $cmd == "repo-remove" ]] ; then + echo "$(gettext "Example: repo-remove /path/to/repo.db.tar.gz kernel26")" + fi } version() { - printf "repo-add, repo-remove (pacman) %s\n\n" "$myver" + cmd="$(basename $0)" + printf "%s (pacman) %s\n\n" "$cmd" "$myver" printf "$(gettext "\ -Copyright (C) 2006-2008 Aaron Griffin <aaron@archlinux.org>.\n\ -Copyright (c) 2007-2008 Dan McGee <dan@archlinux.org>.\n\n\ +Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>\n\n\ This is free software; see the source for copying conditions.\n\ There is NO WARRANTY, to the extent permitted by law.\n")" } @@ -184,14 +193,62 @@ db_remove_delta() return 1 } # end db_remove_delta +check_gpg() { + if ! type -p gpg >/dev/null; then + error "$(gettext "Cannot find the gpg binary! Is gnupg installed?")" + exit 1 # $E_MISSING_PROGRAM + fi +} + +# sign the package database once repackaged +create_signature() { + (( ! SIGN )) && return + local dbfile="$1" + local ret=0 + msg "$(gettext "Signing database...")" + + local SIGNWITHKEY="" + if [[ -n $GPGKEY ]]; then + SIGNWITHKEY="-u ${GPGKEY}" + fi + gpg --detach-sign --use-agent ${SIGNWITHKEY} "$dbfile" &>/dev/null || ret=$? + + if (( ! ret )); then + msg2 "$(gettext "Created signature file %s.")" "$dbfile.sig" + else + warning "$(gettext "Failed to sign package database.")" + fi +} + +# verify the existing package database signature +verify_signature() { + (( ! VERIFY )) && return + local dbfile="$1" + local ret=0 + msg "$(gettext "Verifying database signature...")" + + if [[ ! -f $dbfile.sig ]]; then + warning "$(gettext "No existing signature found, skipping verification.")" + return + fi + gpg --verify "$dbfile.sig" || ret=$? + if (( ! ret )); then + msg2 "$(gettext "Database signature file verified.")" + else + error "$(gettext "Database signature was NOT valid!")" + exit 1 + fi +} + # write an entry to the pacman database # arg1 - path to package db_write_entry() { # blank out all variables local pkgfile="$1" - local pkgname pkgver pkgdesc csize size md5sum url arch builddate packager \ - _groups _licenses _replaces _depends _conflicts _provides _optdepends + local pkgname pkgver pkgdesc csize size url arch builddate packager \ + _groups _licenses _replaces _depends _conflicts _provides _optdepends \ + md5sum sha256sum pgpsig local OLDIFS="$IFS" # IFS (field separator) is only the newline character @@ -219,10 +276,19 @@ db_write_entry() IFS=$OLDIFS - # get md5sum and compressed size of package + csize=$(@SIZECMD@ "$pkgfile") + + # compute checksums + msg2 "$(gettext "Computing checksums...")" md5sum="$(openssl dgst -md5 "$pkgfile")" md5sum="${md5sum##* }" - csize=$(@SIZECMD@ "$pkgfile") + sha256sum="$(openssl dgst -sha256 "$pkgfile")" + sha256sum="${sha256sum##* }" + + # compute base64'd PGP signature + if [[ -f "$pkgfile.sig" ]]; then + pgpsig=$(openssl base64 -in "$pkgfile.sig" | tr -d '\n') + fi # ensure $pkgname and $pkgver variables were found if [[ -z $pkgname || -z $pkgver ]]; then @@ -264,9 +330,12 @@ db_write_entry() [[ -n $csize ]] && echo -e "%CSIZE%\n$csize\n" >>desc [[ -n $size ]] && echo -e "%ISIZE%\n$size\n" >>desc - # compute checksums - msg2 "$(gettext "Computing md5 checksums...")" + # add checksums echo -e "%MD5SUM%\n$md5sum\n" >>desc + echo -e "%SHA256SUM%\n$sha256sum\n" >>desc + + # add PGP sig + [[ -n $pgpsig ]] && echo -e "%PGPSIG%\n$pgpsig\n" >>desc [[ -n $url ]] && echo -e "%URL%\n$url\n" >>desc write_list_entry "LICENSE" "$_licenses" "desc" @@ -352,6 +421,7 @@ check_repo_db() exit 1 fi fi + verify_signature "$REPO_DB_FILE" msg "$(gettext "Extracting database to a temporary location...")" bsdtar -xf "$REPO_DB_FILE" -C "$tmpdir" else @@ -477,24 +547,50 @@ trap 'trap_exit "$(gettext "An unknown error has occured. Exiting...")"' ERR success=0 # parse arguments -for arg in "$@"; do - case "$arg" in +while [[ $# > 0 ]]; do + case "$1" in -q|--quiet) QUIET=1;; -d|--delta) DELTA=1;; -f|--files) WITHFILES=1;; + -s|--sign) + check_gpg + SIGN=1 + if ! gpg --list-key ${GPGKEY} &>/dev/null; then + if [[ ! -z $GPGKEY ]]; then + error "$(gettext "The key ${GPGKEY} does not exist in your keyring.")" + else + error "$(gettext "There is no key in your keyring.")" + fi + exit 1 + fi + ;; + -k|--key) + check_gpg + shift + GPGKEY="$1" + if ! gpg --list-key ${GPGKEY} &>/dev/null; then + error "$(gettext "The key ${GPGKEY} does not exist in your keyring.")" + exit 1 + fi + ;; + -v|--verify) + check_gpg + VERIFY=1 + ;; *) if [[ -z $REPO_DB_FILE ]]; then - REPO_DB_FILE="$arg" + REPO_DB_FILE="$1" LOCKFILE="$REPO_DB_FILE.lck" check_repo_db else case "$cmd" in - repo-add) add $arg && success=1 ;; - repo-remove) remove $arg && success=1 ;; + repo-add) add $1 && success=1 ;; + repo-remove) remove $1 && success=1 ;; esac fi ;; esac + shift done # if at least one operation was a success, re-zip database @@ -519,15 +615,24 @@ if (( success )); then warning "$(gettext "No packages remain, creating empty database.")" bsdtar -c${TAR_OPT}f "$filename" -T /dev/null fi + create_signature "$filename" + popd >/dev/null [[ -f $REPO_DB_FILE ]] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old" + [[ -f $REPO_DB_FILE.sig ]] && rm -f "$REPO_DB_FILE.sig" [[ -f $tmpdir/$filename ]] && mv "$tmpdir/$filename" "$REPO_DB_FILE" + [[ -f $tmpdir/$filename.sig ]] && mv "$tmpdir/$filename.sig" "$REPO_DB_FILE.sig" dblink="${REPO_DB_FILE%.tar.*}" target=${REPO_DB_FILE##*/} ln -sf "$target" "$dblink" 2>/dev/null || \ ln -f "$target" "$dblink" 2>/dev/null || \ cp "$REPO_DB_FILE" "$dblink" + if [[ -f "$target.sig" ]]; then + ln -sf "$target.sig" "$dblink.sig" 2>/dev/null || \ + ln -f "$target.sig" "$dblink.sig" 2>/dev/null || \ + cp "$REPO_DB_FILE.sig" "$dblink.sig" + fi else msg "$(gettext "No packages modified, nothing to do.")" exit 1 diff --git a/src/pacman/Makefile.am b/src/pacman/Makefile.am index 31e8b134..333b8193 100644 --- a/src/pacman/Makefile.am +++ b/src/pacman/Makefile.am @@ -1,6 +1,7 @@ # paths set at make time conffile = ${sysconfdir}/pacman.conf dbpath = ${localstatedir}/lib/pacman/ +gpgdir = ${sysconfdir}/pacman.d/gnupg/ cachedir = ${localstatedir}/cache/pacman/pkg/ logfile = ${localstatedir}/log/pacman.log @@ -10,6 +11,7 @@ DEFS = -DLOCALEDIR=\"@localedir@\" \ -DCONFFILE=\"$(conffile)\" \ -DROOTDIR=\"$(ROOTDIR)\" \ -DDBPATH=\"$(dbpath)\" \ + -DGPGDIR=\"$(gpgdir)\" \ -DCACHEDIR=\"$(cachedir)\" \ -DLOGFILE=\"$(logfile)\" \ @DEFS@ diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 46ff2e88..4ac3b56b 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -81,7 +81,7 @@ static double get_update_timediff(int first_call) } } - return(retval); + return retval; } /* refactored from cb_trans_progress */ @@ -176,7 +176,7 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) } break; case PM_TRANS_EVT_ADD_DONE: - alpm_logaction("installed %s (%s)\n", + alpm_logaction(config->handle, "installed %s (%s)\n", alpm_pkg_get_name(data1), alpm_pkg_get_version(data1)); display_optdepends(data1); @@ -187,7 +187,7 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) } break; case PM_TRANS_EVT_REMOVE_DONE: - alpm_logaction("removed %s (%s)\n", + alpm_logaction(config->handle, "removed %s (%s)\n", alpm_pkg_get_name(data1), alpm_pkg_get_version(data1)); break; @@ -197,7 +197,7 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) } break; case PM_TRANS_EVT_UPGRADE_DONE: - alpm_logaction("upgraded %s (%s -> %s)\n", + 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)); @@ -224,10 +224,10 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2) printf(_("failed.\n")); break; case PM_TRANS_EVT_SCRIPTLET_INFO: - printf("%s", (char*)data1); + printf("%s", (char *)data1); break; case PM_TRANS_EVT_RETRIEVE_START: - printf(_(":: Retrieving packages from %s...\n"), (char*)data1); + printf(_(":: Retrieving packages from %s...\n"), (char *)data1); break; case PM_TRANS_EVT_DISKSPACE_START: if(config->noprogressbar) { @@ -256,8 +256,12 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2, { switch(event) { case PM_TRANS_CONV_INSTALL_IGNOREPKG: - *response = yesno(_(":: %s is in IgnorePkg/IgnoreGroup. Install anyway?"), - alpm_pkg_get_name(data1)); + if(!config->op_s_downloadonly) { + *response = yesno(_(":: %s is in IgnorePkg/IgnoreGroup. Install anyway?"), + alpm_pkg_get_name(data1)); + } else { + *response = 1; + } break; case PM_TRANS_CONV_REPLACE_PKG: *response = yesno(_(":: Replace %s with %s/%s?"), @@ -400,7 +404,7 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent, } infolen = cols * 6 / 10; - if (infolen < 50) { + if(infolen < 50) { infolen = 50; } @@ -494,10 +498,11 @@ 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, f_xfered = 0.0; + double rate = 0.0, timediff = 0.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; - char rate_size = 'K', xfered_size = 'K'; const int cols = getcols(0); @@ -510,7 +515,7 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) } infolen = cols * 6 / 10; - if (infolen < 50) { + if(infolen < 50) { infolen = 50; } /* explanation of magic 28 number at the end */ @@ -561,7 +566,7 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) diff_sec = current_time.tv_sec - initial_time.tv_sec; diff_usec = current_time.tv_usec - initial_time.tv_usec; timediff = diff_sec + (diff_usec / 1000000.0); - rate = xfered / (timediff * 1024.0); + rate = xfered / timediff; /* round elapsed time to the nearest second */ eta_s = (int)(timediff + 0.5); @@ -573,10 +578,10 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) /* return if the calling interval was too short */ return; } - rate = (xfered - xfered_last) / (timediff * 1024.0); + rate = (xfered - xfered_last) / timediff; /* average rate to reduce jumpiness */ rate = (rate + 2 * rate_last) / 3; - eta_s = (total - xfered) / (rate * 1024.0); + eta_s = (total - xfered) / rate; rate_last = rate; xfered_last = xfered; } @@ -630,37 +635,13 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total) } - /* Awesome formatting for progress bar. We need a mess of Kb->Mb->Gb stuff - * here. We'll use limit of 2048 for each until we get some empirical */ - /* rate_size = 'K'; was set above */ - if(rate > 2048.0) { - rate /= 1024.0; - rate_size = 'M'; - if(rate > 2048.0) { - rate /= 1024.0; - rate_size = 'G'; - /* we should not go higher than this for a few years (9999.9 Gb/s?)*/ - } - } - - f_xfered = xfered / 1024.0; /* convert to K by default */ - /* xfered_size = 'K'; was set above */ - if(f_xfered > 2048.0) { - f_xfered /= 1024.0; - xfered_size = 'M'; - if(f_xfered > 2048.0) { - f_xfered /= 1024.0; - xfered_size = 'G'; - /* I should seriously hope that archlinux packages never break - * the 9999.9GB mark... we'd have more serious problems than the progress - * bar in pacman */ - } - } + rate_human = humanize_size((off_t)rate, '\0', 0, &rate_label); + xfered_human = humanize_size(xfered, '\0', 0, &xfered_label); /* 1 space + filenamelen + 1 space + 7 for size + 1 + 7 for rate + 2 for /s + 1 space + 8 for eta */ - printf(" %ls%-*s %6.1f%c %#6.1f%c/s %02u:%02u:%02u", wcfname, - padwid, "", f_xfered, xfered_size, - rate, rate_size, eta_h, eta_m, eta_s); + printf(" %ls%-*s %6.1f%s %#6.1f%s/s %02u:%02u:%02u", wcfname, + padwid, "", xfered_human, xfered_label, rate_human, rate_label, + eta_h, eta_m, eta_s); free(fname); free(wcfname); diff --git a/src/pacman/conf.c b/src/pacman/conf.c index e2a168ee..82f525c4 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -20,13 +20,21 @@ #include "config.h" +#include <errno.h> +#include <glob.h> +#include <limits.h> #include <stdlib.h> #include <stdio.h> #include <string.h> /* strdup */ +#include <sys/stat.h> +#include <sys/utsname.h> /* uname */ +#include <unistd.h> /* pacman */ #include "conf.h" #include "util.h" +#include "pacman.h" +#include "callback.h" /* global config variable */ config_t *config = NULL; @@ -38,35 +46,745 @@ config_t *config_new(void) pm_fprintf(stderr, PM_LOG_ERROR, _("malloc failure: could not allocate %zd bytes\n"), sizeof(config_t)); - return(NULL); + return NULL; } /* defaults which may get overridden later */ newconfig->op = PM_OP_MAIN; newconfig->logmask = PM_LOG_ERROR | PM_LOG_WARNING; - /* CONFFILE is defined at compile-time */ newconfig->configfile = strdup(CONFFILE); + newconfig->sigverify = PM_PGP_VERIFY_UNKNOWN; - return(newconfig); + return newconfig; } int config_free(config_t *oldconfig) { if(oldconfig == NULL) { - return(-1); + return -1; } FREELIST(oldconfig->holdpkg); FREELIST(oldconfig->syncfirst); + FREELIST(oldconfig->ignorepkg); + FREELIST(oldconfig->ignoregrp); + FREELIST(oldconfig->noupgrade); + FREELIST(oldconfig->noextract); free(oldconfig->configfile); free(oldconfig->rootdir); free(oldconfig->dbpath); free(oldconfig->logfile); + free(oldconfig->gpgdir); + FREELIST(oldconfig->cachedirs); free(oldconfig->xfercommand); free(oldconfig->print_format); + free(oldconfig->arch); free(oldconfig); oldconfig = NULL; - return(0); + return 0; +} + +/** Helper function for download_with_xfercommand() */ +static char *get_filename(const char *url) { + char *filename = strrchr(url, '/'); + if(filename != NULL) { + filename++; + } + return filename; +} + +/** Helper function for download_with_xfercommand() */ +static char *get_destfile(const char *path, const char *filename) { + char *destfile; + /* len = localpath len + filename len + null */ + size_t len = strlen(path) + strlen(filename) + 1; + destfile = calloc(len, sizeof(char)); + snprintf(destfile, len, "%s%s", path, filename); + + return destfile; +} + +/** Helper function for download_with_xfercommand() */ +static char *get_tempfile(const char *path, const char *filename) { + char *tempfile; + /* len = localpath len + filename len + '.part' len + null */ + size_t len = strlen(path) + strlen(filename) + 6; + tempfile = calloc(len, sizeof(char)); + snprintf(tempfile, len, "%s%s.part", path, filename); + + return tempfile; +} + +/** External fetch callback */ +static int download_with_xfercommand(const char *url, const char *localpath, + int force) { + int ret = 0; + int retval; + int usepart = 0; + struct stat st; + char *parsedcmd,*tempcmd; + char cwd[PATH_MAX]; + int restore_cwd = 0; + char *destfile, *tempfile, *filename; + + if(!config->xfercommand) { + return -1; + } + + filename = get_filename(url); + if(!filename) { + return -1; + } + destfile = get_destfile(localpath, filename); + tempfile = get_tempfile(localpath, filename); + + if(force && stat(tempfile, &st) == 0) { + unlink(tempfile); + } + if(force && stat(destfile, &st) == 0) { + unlink(destfile); + } + + tempcmd = strdup(config->xfercommand); + /* replace all occurrences of %o with fn.part */ + if(strstr(tempcmd, "%o")) { + usepart = 1; + parsedcmd = strreplace(tempcmd, "%o", tempfile); + free(tempcmd); + tempcmd = parsedcmd; + } + /* replace all occurrences of %u with the download URL */ + parsedcmd = strreplace(tempcmd, "%u", url); + free(tempcmd); + + /* save the cwd so we can restore it later */ + if(getcwd(cwd, PATH_MAX) == NULL) { + pm_printf(PM_LOG_ERROR, _("could not get current working directory\n")); + } else { + restore_cwd = 1; + } + + /* cwd to the download directory */ + if(chdir(localpath)) { + pm_printf(PM_LOG_WARNING, _("could not chdir to download directory %s\n"), localpath); + ret = -1; + goto cleanup; + } + /* execute the parsed command via /bin/sh -c */ + pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedcmd); + retval = system(parsedcmd); + + if(retval == -1) { + pm_printf(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); + ret = -1; + } else if(retval != 0) { + /* download failed */ + pm_printf(PM_LOG_DEBUG, "XferCommand command returned non-zero status " + "code (%d)\n", retval); + ret = -1; + } else { + /* download was successful */ + if(usepart) { + rename(tempfile, destfile); + } + ret = 0; + } + +cleanup: + /* restore the old cwd if we have it */ + if(restore_cwd && chdir(cwd) != 0) { + pm_printf(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), + cwd, strerror(errno)); + } + + if(ret == -1) { + /* hack to let an user the time to cancel a download */ + sleep(2); + } + free(destfile); + free(tempfile); + free(parsedcmd); + + return ret; +} + + +int config_set_arch(const char *arch) +{ + if(strcmp(arch, "auto") == 0) { + struct utsname un; + uname(&un); + config->arch = strdup(un.machine); + } else { + config->arch = strdup(arch); + } + pm_printf(PM_LOG_DEBUG, "config: arch: %s\n", config->arch); + return 0; +} + +static pgp_verify_t option_verifysig(const char *value) +{ + pgp_verify_t level; + if(strcmp(value, "Always") == 0) { + level = PM_PGP_VERIFY_ALWAYS; + } else if(strcmp(value, "Optional") == 0) { + level = PM_PGP_VERIFY_OPTIONAL; + } else if(strcmp(value, "Never") == 0) { + level = PM_PGP_VERIFY_NEVER; + } else { + level = PM_PGP_VERIFY_UNKNOWN; + } + pm_printf(PM_LOG_DEBUG, "config: VerifySig = %s (%d)\n", value, level); + return level; +} + +static int process_cleanmethods(alpm_list_t *values) { + alpm_list_t *i; + for(i = values; i; i = alpm_list_next(i)) { + const char *value = i->data; + if(strcmp(value, "KeepInstalled") == 0) { + config->cleanmethod |= PM_CLEAN_KEEPINST; + } else if(strcmp(value, "KeepCurrent") == 0) { + config->cleanmethod |= PM_CLEAN_KEEPCUR; + } else { + pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), + value); + return 1; + } + } + return 0; +} + +/** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm + * settings. Refactored out of the parseconfig code since all of them did + * the exact same thing and duplicated code. + * @param ptr a pointer to the start of the multiple options + * @param option the string (friendly) name of the option, used for messages + * @param list the list to add the option to + */ +static void setrepeatingoption(char *ptr, const char *option, + alpm_list_t **list) +{ + char *q; + + while((q = strchr(ptr, ' '))) { + *q = '\0'; + *list = alpm_list_add(*list, strdup(ptr)); + pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); + ptr = q; + ptr++; + } + *list = alpm_list_add(*list, strdup(ptr)); + pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); +} + +static int _parse_options(const char *key, char *value, + const char *file, int linenum) +{ + if(value == NULL) { + /* options without settings */ + if(strcmp(key, "UseSyslog") == 0) { + config->usesyslog = 1; + pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); + } else if(strcmp(key, "ILoveCandy") == 0) { + config->chomp = 1; + pm_printf(PM_LOG_DEBUG, "config: chomp\n"); + } else if(strcmp(key, "VerbosePkgLists") == 0) { + config->verbosepkglists = 1; + pm_printf(PM_LOG_DEBUG, "config: verbosepkglists\n"); + } else if(strcmp(key, "UseDelta") == 0) { + config->usedelta = 1; + pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); + } else if(strcmp(key, "TotalDownload") == 0) { + config->totaldownload = 1; + pm_printf(PM_LOG_DEBUG, "config: totaldownload\n"); + } else if(strcmp(key, "CheckSpace") == 0) { + config->checkspace = 1; + } else { + pm_printf(PM_LOG_WARNING, + _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), + file, linenum, key, "options"); + } + } else { + /* options with settings */ + if(strcmp(key, "NoUpgrade") == 0) { + setrepeatingoption(value, "NoUpgrade", &(config->noupgrade)); + } else if(strcmp(key, "NoExtract") == 0) { + setrepeatingoption(value, "NoExtract", &(config->noextract)); + } else if(strcmp(key, "IgnorePkg") == 0) { + setrepeatingoption(value, "IgnorePkg", &(config->ignorepkg)); + } else if(strcmp(key, "IgnoreGroup") == 0) { + setrepeatingoption(value, "IgnoreGroup", &(config->ignoregrp)); + } else if(strcmp(key, "HoldPkg") == 0) { + setrepeatingoption(value, "HoldPkg", &(config->holdpkg)); + } else if(strcmp(key, "SyncFirst") == 0) { + setrepeatingoption(value, "SyncFirst", &(config->syncfirst)); + } else if(strcmp(key, "CacheDir") == 0) { + setrepeatingoption(value, "CacheDir", &(config->cachedirs)); + } else if(strcmp(key, "Architecture") == 0) { + if(!config->arch) { + config_set_arch(value); + } + } else if(strcmp(key, "DBPath") == 0) { + /* don't overwrite a path specified on the command line */ + if(!config->dbpath) { + config->dbpath = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", value); + } + } else if(strcmp(key, "RootDir") == 0) { + /* don't overwrite a path specified on the command line */ + if(!config->rootdir) { + config->rootdir = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", value); + } + } else if(strcmp(key, "GPGDir") == 0) { + if(!config->gpgdir) { + config->gpgdir = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: gpgdir: %s\n", value); + } + } else if(strcmp(key, "LogFile") == 0) { + if(!config->logfile) { + config->logfile = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", value); + } + } else if(strcmp(key, "XferCommand") == 0) { + config->xfercommand = strdup(value); + pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", value); + } else if(strcmp(key, "CleanMethod") == 0) { + alpm_list_t *methods = NULL; + setrepeatingoption(value, "CleanMethod", &methods); + if(process_cleanmethods(methods)) { + FREELIST(methods); + return 1; + } + FREELIST(methods); + } else if(strcmp(key, "VerifySig") == 0) { + pgp_verify_t level = option_verifysig(value); + if(level != PM_PGP_VERIFY_UNKNOWN) { + config->sigverify = level; + } else { + pm_printf(PM_LOG_ERROR, + _("config file %s, line %d: directive '%s' has invalid value '%s'\n"), + file, linenum, key, value); + return 1; + } + } else { + pm_printf(PM_LOG_WARNING, + _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), + file, linenum, key, "options"); + } + + } + return 0; +} + +static int _add_mirror(pmdb_t *db, char *value) +{ + const char *dbname = alpm_db_get_name(db); + /* let's attempt a replacement for the current repo */ + char *temp = strreplace(value, "$repo", dbname); + /* let's attempt a replacement for the arch */ + const char *arch = config->arch; + char *server; + if(arch) { + server = strreplace(temp, "$arch", arch); + free(temp); + } else { + if(strstr(temp, "$arch")) { + free(temp); + pm_printf(PM_LOG_ERROR, _("The mirror '%s' contains the $arch" + " variable, but no Architecture is defined.\n"), value); + return 1; + } + server = temp; + } + + if(alpm_db_add_server(db, server) != 0) { + /* pm_errno is set by alpm_db_setserver */ + pm_printf(PM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"), + dbname, server, alpm_strerror(alpm_errno(config->handle))); + free(server); + return 1; + } + + free(server); + return 0; +} + +/** Sets up libalpm global stuff in one go. Called after the command line + * and inital config file parsing. Once this is complete, we can see if any + * paths were defined. If a rootdir was defined and nothing else, we want all + * of our paths to live under the rootdir that was specified. Safe to call + * multiple times (will only do anything the first time). + */ +static int setup_libalpm(void) +{ + int ret = 0; + enum _pmerrno_t err; + pmhandle_t *handle; + + pm_printf(PM_LOG_DEBUG, "setup_libalpm called\n"); + + /* Configure root path first. If it is set and dbpath/logfile were not + * set, then set those as well to reside under the root. */ + if(config->rootdir) { + char path[PATH_MAX]; + if(!config->dbpath) { + snprintf(path, PATH_MAX, "%s/%s", config->rootdir, DBPATH + 1); + config->dbpath = strdup(path); + } + if(!config->logfile) { + snprintf(path, PATH_MAX, "%s/%s", config->rootdir, LOGFILE + 1); + config->logfile = strdup(path); + } + } else { + config->rootdir = strdup(ROOTDIR); + if(!config->dbpath) { + config->dbpath = strdup(DBPATH); + } + } + + /* initialize library */ + handle = alpm_initialize(config->rootdir, config->dbpath, &err); + if(!handle) { + pm_printf(PM_LOG_ERROR, _("failed to initialize alpm library (%s)\n"), + alpm_strerror(err)); + return -1; + } + config->handle = handle; + + alpm_option_set_logcb(handle, cb_log); + alpm_option_set_dlcb(handle, cb_dl_progress); + + config->logfile = config->logfile ? config->logfile : strdup(LOGFILE); + ret = alpm_option_set_logfile(handle, config->logfile); + if(ret != 0) { + pm_printf(PM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"), + config->logfile, alpm_strerror(alpm_errno(config->handle))); + return ret; + } + + /* Set GnuPG's home directory. This is not relative to rootdir, even if + * rootdir is defined. Reasoning: gpgdir contains configuration data. */ + config->gpgdir = config->gpgdir ? config->gpgdir : strdup(GPGDIR); + ret = alpm_option_set_signaturedir(handle, config->gpgdir); + if(ret != 0) { + pm_printf(PM_LOG_ERROR, _("problem setting gpgdir '%s' (%s)\n"), + config->gpgdir, alpm_strerror(alpm_errno(config->handle))); + return ret; + } + + /* add a default cachedir if one wasn't specified */ + if(config->cachedirs == NULL) { + alpm_option_add_cachedir(handle, CACHEDIR); + } else { + alpm_option_set_cachedirs(handle, config->cachedirs); + } + + if(config->sigverify != PM_PGP_VERIFY_UNKNOWN) { + alpm_option_set_default_sigverify(handle, config->sigverify); + } + + if(config->xfercommand) { + alpm_option_set_fetchcb(handle, download_with_xfercommand); + } + + if(config->totaldownload) { + alpm_option_set_totaldlcb(handle, cb_dl_total); + } + + 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_ignorepkgs(handle, config->ignorepkg); + alpm_option_set_ignoregrps(handle, config->ignoregrp); + alpm_option_set_noupgrades(handle, config->noupgrade); + alpm_option_set_noextracts(handle, config->noextract); + + return 0; +} + +/** + * Allows parsing in advance of an entire config section before we start + * calling library methods. + */ +struct section_t { + /* useful for all sections */ + char *name; + int is_options; + /* db section option gathering */ + pgp_verify_t sigverify; + alpm_list_t *servers; +}; + +/** + * Wrap up a section once we have reached the end of it. This should be called + * when a subsequent section is encountered, or when we have reached the end of + * the root config file. Once called, all existing saved config pieces on the + * section struct are freed. + * @param section the current parsed and saved section data + * @param parse_options whether we are parsing options or repo data + * @return 0 on success, 1 on failure + */ +static int finish_section(struct section_t *section, int parse_options) +{ + int ret = 0; + alpm_list_t *i; + pmdb_t *db; + + pm_printf(PM_LOG_DEBUG, "config: finish section '%s'\n", section->name); + + /* parsing options (or nothing)- nothing to do except free the pieces */ + if(!section->name || parse_options || section->is_options) { + goto cleanup; + } + + /* if we are not looking at options sections only, register a db */ + db = alpm_db_register_sync(config->handle, section->name); + if(db == NULL) { + pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"), + section->name, alpm_strerror(alpm_errno(config->handle))); + ret = 1; + goto cleanup; + } + + if(section->sigverify) { + if(alpm_db_set_pgp_verify(db, section->sigverify)) { + pm_printf(PM_LOG_ERROR, + _("could not set verify option for database '%s' (%s)\n"), + section->name, alpm_strerror(alpm_errno(config->handle))); + ret = 1; + goto cleanup; + } + } + + for(i = section->servers; i; i = alpm_list_next(i)) { + char *value = alpm_list_getdata(i); + if(_add_mirror(db, value) != 0) { + pm_printf(PM_LOG_ERROR, + _("could not add mirror '%s' to database '%s' (%s)\n"), + value, section->name, alpm_strerror(alpm_errno(config->handle))); + ret = 1; + goto cleanup; + } + free(value); + } + +cleanup: + alpm_list_free(section->servers); + section->servers = NULL; + section->sigverify = 0; + free(section->name); + section->name = NULL; + return ret; +} + +/** The "real" parseconfig. Each "Include" directive will recall this method so + * recursion and stack depth are limited to 10 levels. The publicly visible + * parseconfig calls this with a NULL section argument so we can recall from + * within ourself on an include. + * @param file path to the config file + * @param section the current active section + * @param parse_options whether to parse and call methods for the options + * section; if 0, parse and call methods for the repos sections + * @param depth the current recursion depth + * @return 0 on success, 1 on failure + */ +static int _parseconfig(const char *file, struct section_t *section, + int parse_options, int depth) +{ + FILE *fp = NULL; + char line[PATH_MAX]; + int linenum = 0; + int ret = 0; + const int max_depth = 10; + + if(depth >= max_depth) { + pm_printf(PM_LOG_ERROR, + _("config parsing exceeded max recursion depth of %d.\n"), max_depth); + ret = 1; + goto cleanup; + } + + pm_printf(PM_LOG_DEBUG, "config: attempting to read file %s\n", file); + fp = fopen(file, "r"); + if(fp == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s could not be read.\n"), file); + ret = 1; + goto cleanup; + } + + while(fgets(line, PATH_MAX, fp)) { + char *key, *value, *ptr; + size_t line_len; + + linenum++; + strtrim(line); + line_len = strlen(line); + + /* ignore whole line and end of line comments */ + if(line_len == 0 || line[0] == '#') { + continue; + } + if((ptr = strchr(line, '#'))) { + *ptr = '\0'; + } + + if(line[0] == '[' && line[line_len - 1] == ']') { + char *name; + /* only possibility here is a line == '[]' */ + if(line_len <= 2) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: bad section name.\n"), + file, linenum); + ret = 1; + goto cleanup; + } + /* new config section, skip the '[' */ + name = strdup(line + 1); + name[line_len - 2] = '\0'; + /* we're at a new section; perform any post-actions for the prior */ + if(finish_section(section, parse_options)) { + ret = 1; + goto cleanup; + } + pm_printf(PM_LOG_DEBUG, "config: new section '%s'\n", name); + section->name = name; + section->is_options = (strcmp(name, "options") == 0); + continue; + } + + /* directive */ + /* strsep modifies the 'line' string: 'key \0 value' */ + key = line; + value = line; + strsep(&value, "="); + strtrim(key); + strtrim(value); + + if(key == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"), + file, linenum); + ret = 1; + goto cleanup; + } + /* For each directive, compare to the camelcase string. */ + if(section->name == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"), + file, linenum); + ret = 1; + goto cleanup; + } + /* Include is allowed in both options and repo sections */ + if(strcmp(key, "Include") == 0) { + glob_t globbuf; + int globret; + size_t gindex; + + if(value == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), + file, linenum, key); + ret = 1; + goto cleanup; + } + /* Ignore include failures... assume non-critical */ + globret = glob(value, GLOB_NOCHECK, NULL, &globbuf); + switch(globret) { + case GLOB_NOSPACE: + pm_printf(PM_LOG_DEBUG, + "config file %s, line %d: include globbing out of space\n", + file, linenum); + break; + case GLOB_ABORTED: + pm_printf(PM_LOG_DEBUG, + "config file %s, line %d: include globbing read error for %s\n", + file, linenum, value); + break; + case GLOB_NOMATCH: + pm_printf(PM_LOG_DEBUG, + "config file %s, line %d: no include found for %s\n", + file, linenum, value); + break; + default: + for(gindex = 0; gindex < globbuf.gl_pathc; gindex++) { + pm_printf(PM_LOG_DEBUG, "config file %s, line %d: including %s\n", + file, linenum, globbuf.gl_pathv[gindex]); + _parseconfig(globbuf.gl_pathv[gindex], section, parse_options, depth + 1); + } + break; + } + globfree(&globbuf); + continue; + } + if(parse_options && section->is_options) { + /* we are either in options ... */ + if((ret = _parse_options(key, value, file, linenum)) != 0) { + goto cleanup; + } + } else if (!parse_options && !section->is_options) { + /* ... or in a repo section */ + if(strcmp(key, "Server") == 0) { + if(value == NULL) { + pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), + file, linenum, key); + ret = 1; + goto cleanup; + } + section->servers = alpm_list_add(section->servers, strdup(value)); + } else if(strcmp(key, "VerifySig") == 0) { + pgp_verify_t level = option_verifysig(value); + if(level != PM_PGP_VERIFY_UNKNOWN) { + section->sigverify = level; + } else { + pm_printf(PM_LOG_ERROR, + _("config file %s, line %d: directive '%s' has invalid value '%s'\n"), + file, linenum, key, value); + ret = 1; + goto cleanup; + } + } else { + pm_printf(PM_LOG_WARNING, + _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), + file, linenum, key, section->name); + } + } + } + + if(depth == 0) { + ret = finish_section(section, parse_options); + } + +cleanup: + fclose(fp); + pm_printf(PM_LOG_DEBUG, "config: finished parsing %s\n", file); + return ret; +} + +/** Parse a configuration file. + * @param file path to the config file + * @return 0 on success, non-zero on error + */ +int parseconfig(const char *file) +{ + int ret; + struct section_t section; + memset(§ion, 0, sizeof(struct section_t)); + /* the config parse is a two-pass affair. We first parse the entire thing for + * the [options] section so we can get all default and path options set. + * Next, we go back and parse everything but [options]. */ + + /* call the real parseconfig function with a null section & db argument */ + pm_printf(PM_LOG_DEBUG, "parseconfig: options pass\n"); + if((ret = _parseconfig(file, §ion, 1, 0))) { + return ret; + } + if((ret = setup_libalpm())) { + return ret; + } + /* second pass, repo section parsing */ + pm_printf(PM_LOG_DEBUG, "parseconfig: repo pass\n"); + return _parseconfig(file, §ion, 0, 0); } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 92c379fc..4c44bfdd 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -32,6 +32,10 @@ typedef struct __config_t { unsigned short noprogressbar; unsigned short logmask; unsigned short print; + unsigned short checkspace; + unsigned short usesyslog; + unsigned short usedelta; + char *arch; char *print_format; /* unfortunately, we have to keep track of paths both here and in the library * because they can come from both the command line or config file, and we @@ -40,7 +44,8 @@ typedef struct __config_t { char *rootdir; char *dbpath; char *logfile; - /* TODO how to handle cachedirs? */ + char *gpgdir; + alpm_list_t *cachedirs; unsigned short op_q_isfile; unsigned short op_q_info; @@ -63,20 +68,31 @@ typedef struct __config_t { unsigned short op_s_upgrade; unsigned short group; - pmtransflag_t flags; unsigned short noask; unsigned int ask; + pmtransflag_t flags; + pgp_verify_t sigverify; /* conf file options */ - unsigned short chomp; /* I Love Candy! */ - unsigned short showsize; /* show individual package sizes */ + /* I Love Candy! */ + unsigned short chomp; + /* format target pkg lists as table */ + unsigned short verbosepkglists; /* When downloading, display the amount downloaded, rate, ETA, and percent * downloaded of the total download list */ unsigned short totaldownload; - unsigned short cleanmethod; /* select -Sc behavior */ + /* select -Sc behavior */ + unsigned short cleanmethod; alpm_list_t *holdpkg; alpm_list_t *syncfirst; + alpm_list_t *ignorepkg; + alpm_list_t *ignoregrp; + alpm_list_t *noupgrade; + alpm_list_t *noextract; char *xfercommand; + + /* our connection to libalpm */ + pmhandle_t *handle; } config_t; /* Operations */ @@ -106,7 +122,8 @@ enum { OP_NEEDED, OP_ASEXPLICIT, OP_ARCH, - OP_PRINTFORMAT + OP_PRINTFORMAT, + OP_GPGDIR }; /* clean method */ @@ -121,6 +138,8 @@ extern config_t *config; config_t *config_new(void); int config_free(config_t *oldconfig); +int config_set_arch(const char *arch); +int parseconfig(const char *file); #endif /* _PM_CONF_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/database.c b/src/pacman/database.c index 36433f33..292fa54a 100644 --- a/src/pacman/database.c +++ b/src/pacman/database.c @@ -20,7 +20,6 @@ #include "config.h" -#include <stdlib.h> #include <stdio.h> #include <alpm.h> @@ -47,7 +46,7 @@ int pacman_database(alpm_list_t *targets) if(targets == NULL) { pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); - return(1); + return 1; } if(config->flags & PM_TRANS_FLAG_ALLDEPS) { /* --asdeps */ @@ -56,20 +55,20 @@ int pacman_database(alpm_list_t *targets) reason = PM_PKG_REASON_EXPLICIT; } else { pm_printf(PM_LOG_ERROR, _("no install reason specified (use -h for help)\n")); - return(1); + return 1; } /* Lock database */ if(trans_init(0) == -1) { - return(1); + return 1; } - db_local = alpm_option_get_localdb(); + db_local = alpm_option_get_localdb(config->handle); for(i = targets; i; i = alpm_list_next(i)) { char *pkgname = i->data; if(alpm_db_set_pkgreason(db_local, pkgname, reason) == -1) { pm_printf(PM_LOG_ERROR, _("could not set install reason for package %s (%s)\n"), - pkgname, alpm_strerrorlast()); + pkgname, alpm_strerror(alpm_errno(config->handle))); retval = 1; } else { if(reason == PM_PKG_REASON_DEPEND) { @@ -82,9 +81,9 @@ int pacman_database(alpm_list_t *targets) /* Unlock database */ if(trans_release() == -1) { - return(1); + return 1; } - return(retval); + return retval; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/deptest.c b/src/pacman/deptest.c index 8895b487..99abd72d 100644 --- a/src/pacman/deptest.c +++ b/src/pacman/deptest.c @@ -20,23 +20,20 @@ #include "config.h" -#include <stdlib.h> #include <stdio.h> -#include <string.h> #include <alpm.h> #include <alpm_list.h> /* pacman */ #include "pacman.h" -#include "util.h" #include "conf.h" int pacman_deptest(alpm_list_t *targets) { alpm_list_t *i; alpm_list_t *deps = NULL; - pmdb_t *localdb = alpm_option_get_localdb(); + pmdb_t *localdb = alpm_option_get_localdb(config->handle); for(i = targets; i; i = alpm_list_next(i)) { char *target = alpm_list_getdata(i); @@ -47,7 +44,7 @@ int pacman_deptest(alpm_list_t *targets) } if(deps == NULL) { - return(0); + return 0; } for(i = deps; i; i = alpm_list_next(i)) { @@ -56,7 +53,7 @@ int pacman_deptest(alpm_list_t *targets) printf("%s\n", dep); } alpm_list_free(deps); - return(127); + return 127; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/package.c b/src/pacman/package.c index 77a5ee72..9cdb4877 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -26,7 +26,6 @@ #include <unistd.h> #include <limits.h> #include <errno.h> -#include <wchar.h> #include <alpm.h> #include <alpm_list.h> @@ -34,23 +33,25 @@ /* pacman */ #include "package.h" #include "util.h" +#include "conf.h" #define CLBUF_SIZE 4096 -/* Display the content of a package - * - * levels: - * <-1 - sync package, extra information (required by) [-Sii] - * -1 - sync package, normal level [-Si] - * =0 - file query [-Qip] - * 1 - localdb query, normal level [-Qi] - * >1 - localdb query, extra information (backup files) [-Qii] +/** + * Display the details of a package. + * Extra information entails 'required by' info for sync packages and backup + * files info for local packages. + * @param pkg package to display information for + * @param from the type of package we are dealing with + * @param extra should we show extra information */ -void dump_pkg_full(pmpkg_t *pkg, int level) +void dump_pkg_full(pmpkg_t *pkg, enum pkg_from from, int extra) { const char *reason; time_t bdate, idate; char bdatestr[50] = "", idatestr[50] = ""; + const char *label; + double size; const alpm_list_t *i; alpm_list_t *requiredby = NULL, *depstrings = NULL; @@ -82,16 +83,20 @@ void dump_pkg_full(pmpkg_t *pkg, int level) /* turn depends list into a text list */ for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { - pmdepend_t *dep = (pmdepend_t*)alpm_list_getdata(i); + pmdepend_t *dep = (pmdepend_t *)alpm_list_getdata(i); depstrings = alpm_list_add(depstrings, alpm_dep_compute_string(dep)); } - if(level > 0 || level < -1) { + if(extra || from == PKG_FROM_LOCALDB) { /* compute this here so we don't get a pause in the middle of output */ requiredby = alpm_pkg_compute_requiredby(pkg); } /* actual output */ + if(from == PKG_FROM_SYNCDB) { + string_display(_("Repository :"), + alpm_db_get_name(alpm_pkg_get_db(pkg))); + } string_display(_("Name :"), alpm_pkg_get_name(pkg)); string_display(_("Version :"), alpm_pkg_get_version(pkg)); string_display(_("URL :"), alpm_pkg_get_url(pkg)); @@ -100,42 +105,41 @@ void dump_pkg_full(pmpkg_t *pkg, int level) list_display(_("Provides :"), alpm_pkg_get_provides(pkg)); list_display(_("Depends On :"), depstrings); list_display_linebreak(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg)); - if(level > 0 || level < -1) { + if(extra || from == PKG_FROM_LOCALDB) { list_display(_("Required By :"), requiredby); } list_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg)); list_display(_("Replaces :"), alpm_pkg_get_replaces(pkg)); - if(level < 0) { - printf(_("Download Size : %6.2f K\n"), - (double)alpm_pkg_get_size(pkg) / 1024.0); - } - if(level == 0) { - printf(_("Compressed Size: %6.2f K\n"), - (double)alpm_pkg_get_size(pkg) / 1024.0); + + size = humanize_size(alpm_pkg_get_size(pkg), 'K', 1, &label); + if(from == PKG_FROM_SYNCDB) { + printf(_("Download Size : %6.2f %s\n"), size, label); + } else if(from == PKG_FROM_FILE) { + printf(_("Compressed Size: %6.2f %s\n"), size, label); } - printf(_("Installed Size : %6.2f K\n"), - (double)alpm_pkg_get_isize(pkg) / 1024.0); + size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 1, &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(level > 0) { + if(from == PKG_FROM_LOCALDB) { string_display(_("Install Date :"), idatestr); string_display(_("Install Reason :"), reason); } - if(level >= 0) { + if(from == PKG_FROM_FILE || from == PKG_FROM_LOCALDB) { string_display(_("Install Script :"), alpm_pkg_has_scriptlet(pkg) ? _("Yes") : _("No")); } - /* MD5 Sum for sync package */ - if(level < 0) { + if(from == PKG_FROM_SYNCDB) { string_display(_("MD5 Sum :"), alpm_pkg_get_md5sum(pkg)); } string_display(_("Description :"), alpm_pkg_get_desc(pkg)); /* Print additional package info if info flag passed more than once */ - if(level > 1) { + if(from == PKG_FROM_LOCALDB && extra) { dump_pkg_backups(pkg); } @@ -146,23 +150,11 @@ void dump_pkg_full(pmpkg_t *pkg, int level) FREELIST(requiredby); } -/* Display the content of a sync package - */ -void dump_pkg_sync(pmpkg_t *pkg, const char *treename, int level) -{ - if(pkg == NULL) { - return; - } - string_display(_("Repository :"), treename); - /* invert the level since we are a sync package */ - dump_pkg_full(pkg, -level); -} - static const char *get_backup_file_status(const char *root, const char *filename, const char *expected_md5) { char path[PATH_MAX]; - char *ret; + const char *ret; snprintf(path, PATH_MAX, "%s%s", root, filename); @@ -173,11 +165,11 @@ static const char *get_backup_file_status(const char *root, if(md5sum == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, _("could not calculate checksums for %s\n"), path); - return(NULL); + return NULL; } /* if checksums don't match, file has been modified */ - if (strcmp(md5sum, expected_md5) != 0) { + if(strcmp(md5sum, expected_md5) != 0) { ret = "MODIFIED"; } else { ret = "UNMODIFIED"; @@ -195,7 +187,7 @@ static const char *get_backup_file_status(const char *root, ret = "UNKNOWN"; } } - return(ret); + return ret; } /* Display list of backup files and their modification states @@ -203,7 +195,7 @@ static const char *get_backup_file_status(const char *root, void dump_pkg_backups(pmpkg_t *pkg) { alpm_list_t *i; - const char *root = alpm_option_get_root(); + const char *root = alpm_option_get_root(config->handle); printf(_("Backup Files:\n")); if(alpm_pkg_get_backup(pkg)) { /* package has backup files, so print them */ @@ -236,7 +228,7 @@ void dump_pkg_files(pmpkg_t *pkg, int quiet) pkgname = alpm_pkg_get_name(pkg); pkgfiles = alpm_pkg_get_files(pkg); - root = alpm_option_get_root(); + root = alpm_option_get_root(config->handle); for(i = pkgfiles; i; i = alpm_list_next(i)) { filestr = alpm_list_getdata(i); diff --git a/src/pacman/package.h b/src/pacman/package.h index 26333c5a..7a5e5853 100644 --- a/src/pacman/package.h +++ b/src/pacman/package.h @@ -22,8 +22,14 @@ #include <alpm.h> -void dump_pkg_full(pmpkg_t *pkg, int level); -void dump_pkg_sync(pmpkg_t *pkg, const char *treename, int level); +/* TODO it would be nice if we didn't duplicate a backend type */ +enum pkg_from { + PKG_FROM_FILE = 1, + PKG_FROM_LOCALDB, + PKG_FROM_SYNCDB +}; + +void dump_pkg_full(pmpkg_t *pkg, enum pkg_from from, int extra); void dump_pkg_backups(pmpkg_t *pkg); void dump_pkg_files(pmpkg_t *pkg, int quiet); diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 347d8af9..afc79f6f 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -36,12 +36,9 @@ #include <signal.h> #include <unistd.h> #include <sys/types.h> -#include <sys/stat.h> #include <sys/utsname.h> /* uname */ #include <locale.h> /* setlocale */ -#include <time.h> /* time_t */ #include <errno.h> -#include <glob.h> #if defined(PACMAN_DEBUG) && defined(HAVE_MCHECK_H) #include <mcheck.h> /* debug tracing (mtrace) */ #endif @@ -53,9 +50,7 @@ /* pacman */ #include "pacman.h" #include "util.h" -#include "callback.h" #include "conf.h" -#include "package.h" /* list of targets specified on command line */ static alpm_list_t *pm_targets; @@ -66,9 +61,9 @@ static int options_cmp(const void *p1, const void *p2) const char *s1 = p1; const char *s2 = p2; - if(s1 == s2) return(0); - if(!s1) return(-1); - if(!s2) return(1); + if(s1 == s2) return 0; + if(!s1) return -1; + if(!s2) return 1; /* First skip all spaces in both strings */ while(isspace((unsigned char)*s1)) { s1++; @@ -87,15 +82,15 @@ static int options_cmp(const void *p1, const void *p2) s2++; } else if(*s2 == '-') { /* s1 short, s2 long */ - return(-1); + return -1; } else if(*s1 == '-') { /* s1 long, s2 short */ - return(1); + return 1; } /* two short -> strcmp */ } - return(strcmp(s1, s2)); + return strcmp(s1, s2); } /** Display usage/syntax for the specified operation. @@ -170,7 +165,7 @@ static void usage(int op, const char * const myname) addlist(_(" -w, --downloadonly download packages but do not install/upgrade anything\n")); addlist(_(" -y, --refresh download fresh package databases from the server\n")); addlist(_(" --needed don't reinstall up to date packages\n")); - } else if (op == PM_OP_DATABASE) { + } else if(op == PM_OP_DATABASE) { printf("%s: %s {-D --database} <%s> <%s>\n", str_usg, myname, str_opt, str_pkg); printf("%s:\n", str_opt); addlist(_(" --asdeps mark packages as non-explicitly installed\n")); @@ -207,6 +202,7 @@ static void usage(int op, const char * const myname) addlist(_(" --cachedir <dir> set an alternate package cache location\n")); addlist(_(" --config <path> set an alternate configuration file\n")); addlist(_(" --debug display debug messages\n")); + addlist(_(" --gpgdir <path> set an alternate home directory for GnuPG\n")); addlist(_(" --logfile <path> set an alternate log file\n")); addlist(_(" --noconfirm do not ask for any confirmation\n")); } @@ -239,7 +235,7 @@ static void version(void) static void localize(void) { static int init = 0; - if (!init) { + if(!init) { setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); @@ -261,27 +257,14 @@ static void setuseragent(void) setenv("HTTP_USER_AGENT", agent, 0); } -static void setarch(const char *arch) -{ - if (strcmp(arch, "auto") == 0) { - struct utsname un; - uname(&un); - pm_printf(PM_LOG_DEBUG, "config: Architecture: %s\n", un.machine); - alpm_option_set_arch(un.machine); - } else { - pm_printf(PM_LOG_DEBUG, "config: Architecture: %s\n", arch); - alpm_option_set_arch(arch); - } -} - /** Free the resources. * * @param ret the return value */ static void cleanup(int ret) { /* free alpm library resources */ - if(alpm_release() == -1) { - pm_printf(PM_LOG_ERROR, "%s\n", alpm_strerrorlast()); + if(config->handle && alpm_release(config->handle) == -1) { + pm_printf(PM_LOG_ERROR, "error releasing alpm library\n"); } /* free memory */ @@ -302,7 +285,7 @@ static ssize_t xwrite(int fd, const void *buf, size_t count) do { ret = write(fd, buf, count); } while(ret == -1 && errno == EINTR); - return(ret); + return ret; } /** Catches thrown signals. Performs necessary cleanup to ensure database is @@ -321,98 +304,34 @@ static void handler(int signum) xwrite(out, msg1, strlen(msg1)); xwrite(err, msg2, strlen(msg2)); exit(signum); - } else if((signum == SIGINT)) { + } else if(signum == SIGINT) { const char *msg = "\nInterrupt signal received\n"; xwrite(err, msg, strlen(msg)); - if(alpm_trans_interrupt() == 0) { + if(alpm_trans_interrupt(config->handle) == 0) { /* a transaction is being interrupted, don't exit pacman yet. */ return; } /* no commiting transaction, we can release it now and then exit pacman */ - alpm_trans_release(); + alpm_trans_release(config->handle); /* output a newline to be sure we clear any line we may be on */ xwrite(out, "\n", 1); } cleanup(signum); } -/** Sets all libalpm required paths in one go. Called after the command line - * and inital config file parsing. Once this is complete, we can see if any - * paths were defined. If a rootdir was defined and nothing else, we want all - * of our paths to live under the rootdir that was specified. Safe to call - * multiple times (will only do anything the first time). - */ -static void setlibpaths(void) -{ - static int init = 0; - if (!init) { - int ret = 0; - - pm_printf(PM_LOG_DEBUG, "setlibpaths() called\n"); - /* Configure root path first. If it is set and dbpath/logfile were not - * set, then set those as well to reside under the root. */ - if(config->rootdir) { - char path[PATH_MAX]; - ret = alpm_option_set_root(config->rootdir); - if(ret != 0) { - pm_printf(PM_LOG_ERROR, _("problem setting rootdir '%s' (%s)\n"), - config->rootdir, alpm_strerrorlast()); - cleanup(ret); - } - if(!config->dbpath) { - /* omit leading slash from our static DBPATH, root handles it */ - snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), DBPATH + 1); - config->dbpath = strdup(path); - } - if(!config->logfile) { - /* omit leading slash from our static LOGFILE path, root handles it */ - snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), LOGFILE + 1); - config->logfile = strdup(path); - } - } - /* Set other paths if they were configured. Note that unless rootdir - * was left undefined, these two paths (dbpath and logfile) will have - * been set locally above, so the if cases below will now trigger. */ - if(config->dbpath) { - ret = alpm_option_set_dbpath(config->dbpath); - if(ret != 0) { - pm_printf(PM_LOG_ERROR, _("problem setting dbpath '%s' (%s)\n"), - config->dbpath, alpm_strerrorlast()); - cleanup(ret); - } - } - if(config->logfile) { - ret = alpm_option_set_logfile(config->logfile); - if(ret != 0) { - pm_printf(PM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"), - config->logfile, alpm_strerrorlast()); - cleanup(ret); - } - } +#define check_optarg() if(!optarg) { return 1; } - /* add a default cachedir if one wasn't specified */ - if(alpm_option_get_cachedirs() == NULL) { - alpm_option_add_cachedir(CACHEDIR); - } - init = 1; - } -} - -#define check_optarg() if(!optarg) { return(1); } - -typedef void (*fn_add) (const char *s); - -static int parsearg_util_addlist(fn_add fn) +static int parsearg_util_addlist(alpm_list_t **list) { - alpm_list_t *list = NULL, *item = NULL; /* lists for splitting strings */ + alpm_list_t *split, *item; check_optarg(); - list = strsplit(optarg, ','); - for(item = list; item; item = alpm_list_next(item)) { - fn((char *)alpm_list_getdata(item)); + split = strsplit(optarg, ','); + for(item = split; item; item = alpm_list_next(item)) { + *list = alpm_list_add(*list, item->data); } - FREELIST(list); - return(0); + alpm_list_free(split); + return 0; } /** Helper function for parsing operation from command-line arguments. @@ -449,9 +368,9 @@ static int parsearg_op(int opt, int dryrun) if(dryrun) break; config->help = 1; break; default: - return(1); + return 1; } - return(0); + return 0; } /** Helper functions for parsing command-line arguments. @@ -461,7 +380,10 @@ static int parsearg_op(int opt, int dryrun) static int parsearg_global(int opt) { switch(opt) { - case OP_ARCH: check_optarg(); setarch(optarg); break; + case OP_ARCH: + check_optarg(); + config_set_arch(strdup(optarg)); + break; case OP_ASK: check_optarg(); config->noask = 1; @@ -469,11 +391,7 @@ static int parsearg_global(int opt) break; case OP_CACHEDIR: check_optarg(); - if(alpm_option_add_cachedir(optarg) != 0) { - pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), - optarg, alpm_strerrorlast()); - return(1); - } + config->cachedirs = alpm_list_add(config->cachedirs, strdup(optarg)); break; case OP_CONFIG: check_optarg(); @@ -497,7 +415,7 @@ static int parsearg_global(int opt) default: pm_printf(PM_LOG_ERROR, _("'%s' is not a valid debug level\n"), optarg); - return(1); + return 1; } } else { config->logmask |= PM_LOG_DEBUG; @@ -505,6 +423,9 @@ static int parsearg_global(int opt) /* progress bars get wonky with debug on, shut them off */ config->noprogressbar = 1; break; + case OP_GPGDIR: + config->gpgdir = strdup(optarg); + break; case OP_LOGFILE: check_optarg(); config->logfile = strndup(optarg, PATH_MAX); @@ -516,9 +437,9 @@ static int parsearg_global(int opt) break; case 'r': check_optarg(); config->rootdir = strdup(optarg); break; case 'v': (config->verbose)++; break; - default: return(1); + default: return 1; } - return(0); + return 0; } static int parsearg_database(int opt) @@ -526,9 +447,9 @@ static int parsearg_database(int opt) switch(opt) { case OP_ASDEPS: config->flags |= PM_TRANS_FLAG_ALLDEPS; break; case OP_ASEXPLICIT: config->flags |= PM_TRANS_FLAG_ALLEXPLICIT; break; - default: return(1); + default: return 1; } - return(0); + return 0; } static int parsearg_query(int opt) @@ -548,9 +469,9 @@ static int parsearg_query(int opt) case 's': config->op_q_search = 1; break; case 't': config->op_q_unrequired = 1; break; case 'u': config->op_q_upgrade = 1; break; - default: return(1); + default: return 1; } - return(0); + return 0; } /* options common to -S -R -U */ @@ -572,15 +493,15 @@ static int parsearg_trans(int opt) check_optarg(); config->print_format = strdup(optarg); break; - default: return(1); + default: return 1; } - return(0); + return 0; } static int parsearg_remove(int opt) { - if (parsearg_trans(opt) == 0) - return(0); + if(parsearg_trans(opt) == 0) + return 0; switch(opt) { case 'c': config->flags |= PM_TRANS_FLAG_CASCADE; break; case 'n': config->flags |= PM_TRANS_FLAG_NOSAVE; break; @@ -592,35 +513,35 @@ static int parsearg_remove(int opt) } break; case 'u': config->flags |= PM_TRANS_FLAG_UNNEEDED; break; - default: return(1); + default: return 1; } - return(0); + return 0; } /* options common to -S -U */ static int parsearg_upgrade(int opt) { - if (parsearg_trans(opt) == 0) - return(0); + if(parsearg_trans(opt) == 0) + return 0; switch(opt) { case 'f': config->flags |= PM_TRANS_FLAG_FORCE; break; case OP_ASDEPS: config->flags |= PM_TRANS_FLAG_ALLDEPS; break; case OP_ASEXPLICIT: config->flags |= PM_TRANS_FLAG_ALLEXPLICIT; break; case OP_IGNORE: - parsearg_util_addlist(alpm_option_add_ignorepkg); + parsearg_util_addlist(&(config->ignorepkg)); break; case OP_IGNOREGROUP: - parsearg_util_addlist(alpm_option_add_ignoregrp); + parsearg_util_addlist(&(config->ignoregrp)); break; - default: return(1); + default: return 1; } - return(0); + return 0; } static int parsearg_sync(int opt) { - if (parsearg_upgrade(opt) == 0) - return(0); + if(parsearg_upgrade(opt) == 0) + return 0; switch(opt) { case OP_NEEDED: config->flags |= PM_TRANS_FLAG_NEEDED; break; case 'c': (config->op_s_clean)++; break; @@ -636,9 +557,9 @@ static int parsearg_sync(int opt) config->flags |= PM_TRANS_FLAG_NOCONFLICTS; break; case 'y': (config->op_s_sync)++; break; - default: return(1); + default: return 1; } - return(0); + return 0; } /** Parse command-line arguments for each operation. @@ -706,6 +627,7 @@ static int parseargs(int argc, char *argv[]) {"asexplicit", no_argument, 0, OP_ASEXPLICIT}, {"arch", required_argument, 0, OP_ARCH}, {"print-format", required_argument, 0, OP_PRINTFORMAT}, + {"gpgdir", required_argument, 0, OP_GPGDIR}, {0, 0, 0, 0} }; @@ -717,22 +639,22 @@ static int parseargs(int argc, char *argv[]) continue; } else if(opt == '?') { /* unknown option, getopt printed an error */ - return(1); + return 1; } parsearg_op(opt, 0); } if(config->op == 0) { pm_printf(PM_LOG_ERROR, _("only one operation may be used at a time\n")); - return(1); + return 1; } if(config->help) { usage(config->op, mbasename(argv[0])); - return(2); + return 2; } if(config->version) { version(); - return(2); + return 2; } /* parse all other options */ @@ -744,7 +666,7 @@ static int parseargs(int argc, char *argv[]) continue; } else if(opt == '?') { /* this should have failed during first pass already */ - return(1); + return 1; } else if(parsearg_op(opt, 1) == 0) { /* opt is an operation */ continue; @@ -771,7 +693,7 @@ static int parseargs(int argc, char *argv[]) result = 1; break; } - if (result == 0) { + if(result == 0) { continue; } @@ -780,7 +702,7 @@ static int parseargs(int argc, char *argv[]) if(result != 0) { /* global option parsing failed, abort */ pm_printf(PM_LOG_ERROR, _("invalid option\n")); - return(result); + return result; } } @@ -790,469 +712,7 @@ static int parseargs(int argc, char *argv[]) optind++; } - return(0); -} - -/* helper for being used with setrepeatingoption */ -static void option_add_holdpkg(const char *name) { - config->holdpkg = alpm_list_add(config->holdpkg, strdup(name)); -} - -/* helper for being used with setrepeatingoption */ -static void option_add_syncfirst(const char *name) { - config->syncfirst = alpm_list_add(config->syncfirst, strdup(name)); -} - -/* helper for being used with setrepeatingoption */ -static void option_add_cleanmethod(const char *value) { - if (strcmp(value, "KeepInstalled") == 0) { - config->cleanmethod |= PM_CLEAN_KEEPINST; - } else if (strcmp(value, "KeepCurrent") == 0) { - config->cleanmethod |= PM_CLEAN_KEEPCUR; - } else { - pm_printf(PM_LOG_ERROR, _("invalid value for 'CleanMethod' : '%s'\n"), - value); - } -} - -/** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm - * settings. Refactored out of the parseconfig code since all of them did - * the exact same thing and duplicated code. - * @param ptr a pointer to the start of the multiple options - * @param option the string (friendly) name of the option, used for messages - * @param optionfunc a function pointer to an alpm_option_add_* function - */ -static void setrepeatingoption(char *ptr, const char *option, - void (*optionfunc)(const char*)) -{ - char *q; - - while((q = strchr(ptr, ' '))) { - *q = '\0'; - (*optionfunc)(ptr); - pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); - ptr = q; - ptr++; - } - (*optionfunc)(ptr); - pm_printf(PM_LOG_DEBUG, "config: %s: %s\n", option, ptr); -} - -static char *get_filename(const char *url) { - char *filename = strrchr(url, '/'); - if(filename != NULL) { - filename++; - } - return(filename); -} - -static char *get_destfile(const char *path, const char *filename) { - char *destfile; - /* len = localpath len + filename len + null */ - size_t len = strlen(path) + strlen(filename) + 1; - destfile = calloc(len, sizeof(char)); - snprintf(destfile, len, "%s%s", path, filename); - - return(destfile); -} - -static char *get_tempfile(const char *path, const char *filename) { - char *tempfile; - /* len = localpath len + filename len + '.part' len + null */ - size_t len = strlen(path) + strlen(filename) + 6; - tempfile = calloc(len, sizeof(char)); - snprintf(tempfile, len, "%s%s.part", path, filename); - - return(tempfile); -} - -/** External fetch callback */ -static int download_with_xfercommand(const char *url, const char *localpath, - int force) { - int ret = 0; - int retval; - int usepart = 0; - struct stat st; - char *parsedcmd,*tempcmd; - char cwd[PATH_MAX]; - int restore_cwd = 0; - char *destfile, *tempfile, *filename; - - if(!config->xfercommand) { - return -1; - } - - filename = get_filename(url); - if(!filename) { - return -1; - } - destfile = get_destfile(localpath, filename); - tempfile = get_tempfile(localpath, filename); - - if(force && stat(tempfile, &st) == 0) { - unlink(tempfile); - } - if(force && stat(destfile, &st) == 0) { - unlink(destfile); - } - - tempcmd = strdup(config->xfercommand); - /* replace all occurrences of %o with fn.part */ - if(strstr(tempcmd, "%o")) { - usepart = 1; - parsedcmd = strreplace(tempcmd, "%o", tempfile); - free(tempcmd); - tempcmd = parsedcmd; - } - /* replace all occurrences of %u with the download URL */ - parsedcmd = strreplace(tempcmd, "%u", url); - free(tempcmd); - - /* save the cwd so we can restore it later */ - if(getcwd(cwd, PATH_MAX) == NULL) { - pm_printf(PM_LOG_ERROR, _("could not get current working directory\n")); - } else { - restore_cwd = 1; - } - - /* cwd to the download directory */ - if(chdir(localpath)) { - pm_printf(PM_LOG_WARNING, _("could not chdir to download directory %s\n"), localpath); - ret = -1; - goto cleanup; - } - /* execute the parsed command via /bin/sh -c */ - pm_printf(PM_LOG_DEBUG, "running command: %s\n", parsedcmd); - retval = system(parsedcmd); - - if(retval == -1) { - pm_printf(PM_LOG_WARNING, _("running XferCommand: fork failed!\n")); - ret = -1; - } else if(retval != 0) { - /* download failed */ - pm_printf(PM_LOG_DEBUG, "XferCommand command returned non-zero status " - "code (%d)\n", retval); - ret = -1; - } else { - /* download was successful */ - if(usepart) { - rename(tempfile, destfile); - } - ret = 0; - } - -cleanup: - /* restore the old cwd if we have it */ - if(restore_cwd && chdir(cwd) != 0) { - pm_printf(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), cwd, strerror(errno)); - } - - if(ret == -1) { - /* hack to let an user the time to cancel a download */ - sleep(2); - } - free(destfile); - free(tempfile); - free(parsedcmd); - - return(ret); -} - -static int _parse_options(const char *key, char *value, - const char *file, int linenum) -{ - if(value == NULL) { - /* options without settings */ - if(strcmp(key, "UseSyslog") == 0) { - alpm_option_set_usesyslog(1); - pm_printf(PM_LOG_DEBUG, "config: usesyslog\n"); - } else if(strcmp(key, "ILoveCandy") == 0) { - config->chomp = 1; - pm_printf(PM_LOG_DEBUG, "config: chomp\n"); - } else if(strcmp(key, "ShowSize") == 0) { - config->showsize = 1; - pm_printf(PM_LOG_DEBUG, "config: showsize\n"); - } else if(strcmp(key, "UseDelta") == 0) { - alpm_option_set_usedelta(1); - pm_printf(PM_LOG_DEBUG, "config: usedelta\n"); - } else if(strcmp(key, "TotalDownload") == 0) { - config->totaldownload = 1; - pm_printf(PM_LOG_DEBUG, "config: totaldownload\n"); - } else if(strcmp(key, "CheckSpace") == 0) { - alpm_option_set_checkspace(1); - } else { - pm_printf(PM_LOG_WARNING, - _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), - file, linenum, key, "options"); - } - } else { - /* options with settings */ - if(strcmp(key, "NoUpgrade") == 0) { - setrepeatingoption(value, "NoUpgrade", alpm_option_add_noupgrade); - } else if(strcmp(key, "NoExtract") == 0) { - setrepeatingoption(value, "NoExtract", alpm_option_add_noextract); - } else if(strcmp(key, "IgnorePkg") == 0) { - setrepeatingoption(value, "IgnorePkg", alpm_option_add_ignorepkg); - } else if(strcmp(key, "IgnoreGroup") == 0) { - setrepeatingoption(value, "IgnoreGroup", alpm_option_add_ignoregrp); - } else if(strcmp(key, "HoldPkg") == 0) { - setrepeatingoption(value, "HoldPkg", option_add_holdpkg); - } else if(strcmp(key, "SyncFirst") == 0) { - setrepeatingoption(value, "SyncFirst", option_add_syncfirst); - } else if(strcmp(key, "Architecture") == 0) { - if(!alpm_option_get_arch()) { - setarch(value); - } - } else if(strcmp(key, "DBPath") == 0) { - /* don't overwrite a path specified on the command line */ - if(!config->dbpath) { - config->dbpath = strdup(value); - pm_printf(PM_LOG_DEBUG, "config: dbpath: %s\n", value); - } - } else if(strcmp(key, "CacheDir") == 0) { - if(alpm_option_add_cachedir(value) != 0) { - pm_printf(PM_LOG_ERROR, _("problem adding cachedir '%s' (%s)\n"), - value, alpm_strerrorlast()); - return(1); - } - pm_printf(PM_LOG_DEBUG, "config: cachedir: %s\n", value); - } else if(strcmp(key, "RootDir") == 0) { - /* don't overwrite a path specified on the command line */ - if(!config->rootdir) { - config->rootdir = strdup(value); - pm_printf(PM_LOG_DEBUG, "config: rootdir: %s\n", value); - } - } else if (strcmp(key, "LogFile") == 0) { - if(!config->logfile) { - config->logfile = strdup(value); - pm_printf(PM_LOG_DEBUG, "config: logfile: %s\n", value); - } - } else if (strcmp(key, "XferCommand") == 0) { - config->xfercommand = strdup(value); - alpm_option_set_fetchcb(download_with_xfercommand); - pm_printf(PM_LOG_DEBUG, "config: xfercommand: %s\n", value); - } else if (strcmp(key, "CleanMethod") == 0) { - setrepeatingoption(value, "CleanMethod", option_add_cleanmethod); - } else { - - pm_printf(PM_LOG_WARNING, - _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), - file, linenum, key, "options"); - } - - } - return(0); -} - -static int _add_mirror(pmdb_t *db, char *value) -{ - const char *dbname = alpm_db_get_name(db); - /* let's attempt a replacement for the current repo */ - char *temp = strreplace(value, "$repo", dbname); - /* let's attempt a replacement for the arch */ - const char *arch = alpm_option_get_arch(); - char *server; - if(arch) { - server = strreplace(temp, "$arch", arch); - free(temp); - } else { - if(strstr(temp, "$arch")) { - free(temp); - pm_printf(PM_LOG_ERROR, _("The mirror '%s' contains the $arch" - " variable, but no Architecture is defined.\n"), value); - return(1); - } - server = temp; - } - - if(alpm_db_setserver(db, server) != 0) { - /* pm_errno is set by alpm_db_setserver */ - pm_printf(PM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"), - dbname, server, alpm_strerrorlast()); - free(server); - return(1); - } - - free(server); - return(0); -} - -/* The real parseconfig. Called with a null section argument by the publicly - * visible parseconfig so we can recall from within ourself on an include */ -static int _parseconfig(const char *file, const char *givensection, - pmdb_t * const givendb) -{ - FILE *fp = NULL; - char line[PATH_MAX+1]; - int linenum = 0; - char *ptr, *section = NULL; - pmdb_t *db = NULL; - int ret = 0; - - pm_printf(PM_LOG_DEBUG, "config: attempting to read file %s\n", file); - fp = fopen(file, "r"); - if(fp == NULL) { - pm_printf(PM_LOG_ERROR, _("config file %s could not be read.\n"), file); - return(1); - } - - /* if we are passed a section, use it as our starting point */ - if(givensection != NULL) { - section = strdup(givensection); - } - /* if we are passed a db, use it as our starting point */ - if(givendb != NULL) { - db = givendb; - } - - while(fgets(line, PATH_MAX, fp)) { - linenum++; - strtrim(line); - - /* ignore whole line and end of line comments */ - if(strlen(line) == 0 || line[0] == '#') { - continue; - } - if((ptr = strchr(line, '#'))) { - *ptr = '\0'; - } - - if(line[0] == '[' && line[strlen(line)-1] == ']') { - /* new config section, skip the '[' */ - ptr = line; - ptr++; - if(section) { - free(section); - } - section = strdup(ptr); - section[strlen(section)-1] = '\0'; - pm_printf(PM_LOG_DEBUG, "config: new section '%s'\n", section); - if(!strlen(section)) { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: bad section name.\n"), - file, linenum); - ret = 1; - goto cleanup; - } - /* if we are not looking at the options section, register a db */ - if(strcmp(section, "options") != 0) { - db = alpm_db_register_sync(section); - if(db == NULL) { - pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)\n"), - section, alpm_strerrorlast()); - ret = 1; - goto cleanup; - } - } - continue; - } - - /* directive */ - char *key, *value; - /* strsep modifies the 'line' string: 'key \0 value' */ - key = line; - value = line; - strsep(&value, "="); - strtrim(key); - strtrim(value); - - if(key == NULL) { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"), - file, linenum); - ret = 1; - goto cleanup; - } - /* For each directive, compare to the camelcase string. */ - if(section == NULL) { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: All directives must belong to a section.\n"), - file, linenum); - ret = 1; - goto cleanup; - } - /* Include is allowed in both options and repo sections */ - if(strcmp(key, "Include") == 0) { - if(value == NULL) { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), - file, linenum, key); - ret = 1; - goto cleanup; - } - /* Ignore include failures... assume non-critical */ - int globret; - glob_t globbuf; - globret = glob(value, GLOB_NOCHECK, NULL, &globbuf); - switch(globret) { - case GLOB_NOSPACE: - pm_printf(PM_LOG_DEBUG, - "config file %s, line %d: include globbing out of space\n", - file, linenum); - break; - case GLOB_ABORTED: - pm_printf(PM_LOG_DEBUG, - "config file %s, line %d: include globbing read error for %s\n", - file, linenum, value); - break; - case GLOB_NOMATCH: - pm_printf(PM_LOG_DEBUG, - "config file %s, line %d: no include found for %s\n", - file, linenum, value); - break; - default: - for(size_t gindex = 0; gindex < globbuf.gl_pathc; gindex++) { - pm_printf(PM_LOG_DEBUG, "config file %s, line %d: including %s\n", - file, linenum, globbuf.gl_pathv[gindex]); - _parseconfig(globbuf.gl_pathv[gindex], section, db); - } - break; - } - globfree(&globbuf); - continue; - } - if(strcmp(section, "options") == 0) { - /* we are either in options ... */ - if((ret = _parse_options(key, value, file, linenum)) != 0) { - goto cleanup; - } - } else { - /* ... or in a repo section */ - if(strcmp(key, "Server") == 0) { - if(value == NULL) { - pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), - file, linenum, key); - ret = 1; - goto cleanup; - } - if(_add_mirror(db, value) != 0) { - ret = 1; - goto cleanup; - } - } else { - pm_printf(PM_LOG_WARNING, - _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), - file, linenum, key, section); - } - } - - } - -cleanup: - fclose(fp); - if(section){ - free(section); - } - /* call setlibpaths here to ensure we have called it at least once */ - setlibpaths(); - pm_printf(PM_LOG_DEBUG, "config: finished parsing %s\n", file); - return(ret); -} - -/** Parse a configuration file. - * @param file path to the config file. - * @return 0 on success, non-zero on error - */ -static int parseconfig(const char *file) -{ - /* call the real parseconfig function with a null section & db argument */ - return(_parseconfig(file, NULL, NULL)); + return 0; } /** print commandline to logfile @@ -1275,7 +735,7 @@ static void cl_to_log(int argc, char* argv[]) *p++ = ' '; } strcpy(p, argv[i]); - alpm_logaction("Running '%s'\n", cl_text); + alpm_logaction(config->handle, "Running '%s'\n", cl_text); free(cl_text); } @@ -1333,21 +793,6 @@ int main(int argc, char *argv[]) config->noprogressbar = 1; } - /* initialize library */ - if(alpm_initialize() == -1) { - pm_printf(PM_LOG_ERROR, _("failed to initialize alpm library (%s)\n"), - alpm_strerrorlast()); - cleanup(EXIT_FAILURE); - } - - /* Setup logging as soon as possible, to print out maximum debugging info */ - alpm_option_set_logcb(cb_log); - alpm_option_set_dlcb(cb_dl_progress); - /* define paths to reasonable defaults */ - alpm_option_set_root(ROOTDIR); - alpm_option_set_dbpath(DBPATH); - alpm_option_set_logfile(LOGFILE); - /* Priority of options: * 1. command line * 2. config file @@ -1384,7 +829,7 @@ int main(int argc, char *argv[]) } } /* check for buffer overflow */ - if (i >= PATH_MAX) { + if(i >= PATH_MAX) { pm_printf(PM_LOG_ERROR, _("buffer overflow detected in arg parsing\n")); cleanup(EXIT_FAILURE); } @@ -1394,7 +839,7 @@ int main(int argc, char *argv[]) line[i] = '\0'; pm_targets = alpm_list_add(pm_targets, strdup(line)); } - if (!freopen(ctermid(NULL), "r", stdin)) { + if(!freopen(ctermid(NULL), "r", stdin)) { pm_printf(PM_LOG_ERROR, _("failed to reopen stdin for reading: (%s)\n"), strerror(errno)); } @@ -1406,11 +851,6 @@ int main(int argc, char *argv[]) cleanup(ret); } - /* set TotalDownload callback if option enabled */ - if(config->totaldownload) { - alpm_option_set_totaldlcb(cb_dl_total); - } - /* noask is meant to be non-interactive */ if(config->noask) { config->noconfirm = 1; @@ -1435,16 +875,17 @@ int main(int argc, char *argv[]) if(config->verbose > 0) { alpm_list_t *i; - printf("Root : %s\n", alpm_option_get_root()); + printf("Root : %s\n", alpm_option_get_root(config->handle)); printf("Conf File : %s\n", config->configfile); - printf("DB Path : %s\n", alpm_option_get_dbpath()); + printf("DB Path : %s\n", alpm_option_get_dbpath(config->handle)); printf("Cache Dirs: "); - for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { - printf("%s ", (char*)alpm_list_getdata(i)); + for(i = alpm_option_get_cachedirs(config->handle); i; i = alpm_list_next(i)) { + printf("%s ", (char *)alpm_list_getdata(i)); } printf("\n"); - printf("Lock File : %s\n", alpm_option_get_lockfile()); - printf("Log File : %s\n", alpm_option_get_logfile()); + 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_signaturedir(config->handle)); list_display("Targets :", pm_targets); } @@ -1480,7 +921,7 @@ int main(int argc, char *argv[]) cleanup(ret); /* not reached */ - return(EXIT_SUCCESS); + return EXIT_SUCCESS; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/pacman.h b/src/pacman/pacman.h index f5b972bb..762e112d 100644 --- a/src/pacman/pacman.h +++ b/src/pacman/pacman.h @@ -24,6 +24,8 @@ /* database.c */ int pacman_database(alpm_list_t *targets); +/* deptest.c */ +int pacman_deptest(alpm_list_t *targets); /* query.c */ int pacman_query(alpm_list_t *targets); /* remove.c */ @@ -33,9 +35,6 @@ int pacman_sync(alpm_list_t *targets); /* upgrade.c */ int pacman_upgrade(alpm_list_t *targets); -/* deptest.c */ -int pacman_deptest(alpm_list_t *targets); - #endif /* _PM_PACMAN_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/query.c b/src/pacman/query.c index 6c63774f..06fd704a 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -26,7 +26,6 @@ #include <string.h> #include <sys/stat.h> #include <errno.h> -#include <unistd.h> #include <alpm.h> #include <alpm_list.h> @@ -41,17 +40,17 @@ static char *resolve_path(const char *file) { char *str = NULL; - str = calloc(PATH_MAX + 1, sizeof(char)); + str = calloc(PATH_MAX, sizeof(char)); if(!str) { - return(NULL); + return NULL; } if(!realpath(file, str)) { free(str); - return(NULL); + return NULL; } - return(str); + return str; } /* check if filename exists in PATH */ @@ -61,10 +60,10 @@ static int search_path(char **filename, struct stat *bufptr) size_t flen; if((envpath = getenv("PATH")) == NULL) { - return(-1); + return -1; } if((envpath = envpathsplit = strdup(envpath)) == NULL) { - return(-1); + return -1; } flen = strlen(*filename); @@ -80,7 +79,7 @@ static int search_path(char **filename, struct stat *bufptr) fullname = malloc(plen + flen + 2); if(!fullname) { free(envpath); - return(-1); + return -1; } sprintf(fullname, "%s/%s", path, *filename); @@ -88,12 +87,12 @@ static int search_path(char **filename, struct stat *bufptr) free(*filename); *filename = fullname; free(envpath); - return(0); + return 0; } free(fullname); } free(envpath); - return(-1); + return -1; } static void print_query_fileowner(const char *filename, pmpkg_t *info) @@ -119,18 +118,18 @@ static int query_fileowner(alpm_list_t *targets) /* This code is here for safety only */ if(targets == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, _("no file was specified for --owns\n")); - return(1); + return 1; } /* Set up our root path buffer. We only need to copy the location of root in * once, then we can just overwrite whatever file was there on the previous * iteration. */ - root = alpm_option_get_root(); + root = alpm_option_get_root(config->handle); strncpy(path, root, PATH_MAX - 1); append = path + strlen(path); max_length = PATH_MAX - (append - path) - 1; - db_local = alpm_option_get_localdb(); + db_local = alpm_option_get_localdb(config->handle); for(t = targets; t; t = alpm_list_next(t)) { char *filename, *dname, *rpath; @@ -171,7 +170,7 @@ static int query_fileowner(alpm_list_t *targets) bname = mbasename(filename); dname = mdirname(filename); /* for files in '/', there is no directory name to match */ - if (strcmp(dname, "") == 0) { + if(strcmp(dname, "") == 0) { rpath = NULL; } else { rpath = resolve_path(dname); @@ -241,7 +240,7 @@ static int query_search(alpm_list_t *targets) { alpm_list_t *i, *searchlist; int freelist; - pmdb_t *db_local = alpm_option_get_localdb(); + pmdb_t *db_local = alpm_option_get_localdb(config->handle); /* if we have a targets list, search for packages matching it */ if(targets) { @@ -252,29 +251,21 @@ static int query_search(alpm_list_t *targets) freelist = 0; } if(searchlist == NULL) { - return(1); + return 1; } for(i = searchlist; i; i = alpm_list_next(i)) { alpm_list_t *grp; pmpkg_t *pkg = alpm_list_getdata(i); - if (!config->quiet) { + 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)); } - /* print the package size with the output if ShowSize option set */ - if(!config->quiet && config->showsize) { - /* Convert byte size to MB */ - double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - printf(" [%.2f MB]", mbsize); - } - - - if (!config->quiet) { + if(!config->quiet) { if((grp = alpm_pkg_get_groups(pkg)) != NULL) { alpm_list_t *k; printf(" ("); @@ -300,7 +291,7 @@ static int query_search(alpm_list_t *targets) if(freelist) { alpm_list_free(searchlist); } - return(0); + return 0; } static int query_group(alpm_list_t *targets) @@ -308,7 +299,7 @@ static int query_group(alpm_list_t *targets) alpm_list_t *i, *j; char *grpname = NULL; int ret = 0; - pmdb_t *db_local = alpm_option_get_localdb(); + pmdb_t *db_local = alpm_option_get_localdb(config->handle); if(targets == NULL) { for(j = alpm_db_get_grpcache(db_local); j; j = alpm_list_next(j)) { @@ -351,7 +342,7 @@ static int is_foreign(pmpkg_t *pkg) { const char *pkgname = alpm_pkg_get_name(pkg); alpm_list_t *j; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle); int match = 0; for(j = sync_dbs; j; j = alpm_list_next(j)) { @@ -363,19 +354,19 @@ static int is_foreign(pmpkg_t *pkg) } } if(match == 0) { - return(1); + return 1; } - return(0); + return 0; } static int is_unrequired(pmpkg_t *pkg) { alpm_list_t *requiredby = alpm_pkg_compute_requiredby(pkg); if(requiredby == NULL) { - return(1); + return 1; } FREELIST(requiredby); - return(0); + return 0; } static int filter(pmpkg_t *pkg) @@ -383,26 +374,27 @@ static int filter(pmpkg_t *pkg) /* check if this package was explicitly installed */ if(config->op_q_explicit && alpm_pkg_get_reason(pkg) != PM_PKG_REASON_EXPLICIT) { - return(0); + return 0; } /* check if this package was installed as a dependency */ if(config->op_q_deps && alpm_pkg_get_reason(pkg) != PM_PKG_REASON_DEPEND) { - return(0); + return 0; } /* check if this pkg isn't in a sync DB */ if(config->op_q_foreign && !is_foreign(pkg)) { - return(0); + return 0; } /* check if this pkg is unrequired */ if(config->op_q_unrequired && !is_unrequired(pkg)) { - return(0); + return 0; } /* check if this pkg is outdated */ - if(config->op_q_upgrade && (alpm_sync_newversion(pkg, alpm_option_get_syncdbs()) == NULL)) { - return(0); + if(config->op_q_upgrade && (alpm_sync_newversion(pkg, + alpm_option_get_syncdbs(config->handle)) == NULL)) { + return 0; } - return(1); + return 1; } /* Loop through the packages. For each package, @@ -415,12 +407,12 @@ static int check(pmpkg_t *pkg) size_t rootlen; char f[PATH_MAX]; - root = alpm_option_get_root(); + root = alpm_option_get_root(config->handle); rootlen = strlen(root); if(rootlen + 1 > PATH_MAX) { /* we are in trouble here */ pm_fprintf(stderr, PM_LOG_ERROR, _("path too long: %s%s\n"), root, ""); - return(1); + return 1; } strcpy(f, root); @@ -454,7 +446,7 @@ static int check(pmpkg_t *pkg) (unsigned long)errors), errors); } - return(errors != 0 ? 1 : 0); + return (errors != 0 ? 1 : 0); } static int display(pmpkg_t *pkg) @@ -463,10 +455,9 @@ static int display(pmpkg_t *pkg) if(config->op_q_info) { if(config->op_q_isfile) { - /* omit info that isn't applicable for a file package */ - dump_pkg_full(pkg, 0); + dump_pkg_full(pkg, PKG_FROM_FILE, 0); } else { - dump_pkg_full(pkg, config->op_q_info); + dump_pkg_full(pkg, PKG_FROM_LOCALDB, config->op_q_info > 1); } } if(config->op_q_list) { @@ -480,13 +471,13 @@ static int display(pmpkg_t *pkg) } if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog && !config->op_q_check) { - if (!config->quiet) { + if(!config->quiet) { printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); } else { printf("%s\n", alpm_pkg_get_name(pkg)); } } - return(ret); + return ret; } int pacman_query(alpm_list_t *targets) @@ -502,25 +493,25 @@ int pacman_query(alpm_list_t *targets) /* search for a package */ if(config->op_q_search) { ret = query_search(targets); - return(ret); + return ret; } /* looking for groups */ if(config->group) { ret = query_group(targets); - return(ret); + return ret; } if(config->op_q_foreign) { /* ensure we have at least one valid sync db set up */ - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle); if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) { pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n")); - return(1); + return 1; } } - db_local = alpm_option_get_localdb(); + db_local = alpm_option_get_localdb(config->handle); /* operations on all packages in the local DB * valid: no-op (plain -Q), list, info, check @@ -528,7 +519,7 @@ int pacman_query(alpm_list_t *targets) if(targets == NULL) { if(config->op_q_isfile || config->op_q_owns) { pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); - return(1); + return 1; } for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) { @@ -544,7 +535,7 @@ int pacman_query(alpm_list_t *targets) if(!match) { ret = 1; } - return(ret); + return ret; } /* Second: operations that require target(s) */ @@ -552,7 +543,7 @@ int pacman_query(alpm_list_t *targets) /* determine the owner of a file */ if(config->op_q_owns) { ret = query_fileowner(targets); - return(ret); + return ret; } /* operations on named packages in the local DB @@ -561,7 +552,7 @@ int pacman_query(alpm_list_t *targets) char *strname = alpm_list_getdata(i); if(config->op_q_isfile) { - alpm_pkg_load(strname, 1, &pkg); + alpm_pkg_load(config->handle, strname, 1, PM_PGP_VERIFY_OPTIONAL, &pkg); } else { pkg = alpm_db_get_pkg(db_local, strname); } @@ -590,7 +581,7 @@ int pacman_query(alpm_list_t *targets) ret = 1; } - return(ret); + return ret; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/remove.c b/src/pacman/remove.c index fb02e242..a4e18941 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -31,34 +31,36 @@ #include "util.h" #include "conf.h" -static int remove_target(char *target) +static int remove_target(const char *target) { pmpkg_t *info; - pmdb_t *db_local = alpm_option_get_localdb(); + pmdb_t *db_local = alpm_option_get_localdb(config->handle); alpm_list_t *p; if((info = alpm_db_get_pkg(db_local, target)) != NULL) { - if(alpm_remove_pkg(info) == -1) { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, alpm_strerrorlast()); - return(-1); + if(alpm_remove_pkg(config->handle, info) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, + alpm_strerror(alpm_errno(config->handle))); + return -1; } - return(0); + return 0; } /* fallback to group */ pmgrp_t *grp = alpm_db_readgrp(db_local, target); if(grp == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': target not found\n", target); - return(-1); + return -1; } for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) { pmpkg_t *pkg = alpm_list_getdata(p); - if(alpm_remove_pkg(pkg) == -1) { - pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, alpm_strerrorlast()); - return(-1); + if(alpm_remove_pkg(config->handle, pkg) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", target, + alpm_strerror(alpm_errno(config->handle))); + return -1; } } - return(0); + return 0; } /** @@ -75,12 +77,12 @@ int pacman_remove(alpm_list_t *targets) if(targets == NULL) { pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); - return(1); + return 1; } /* Step 0: create a new transaction */ if(trans_init(config->flags) == -1) { - return(1); + return 1; } /* Step 1: add targets to the created transaction */ @@ -99,10 +101,11 @@ int pacman_remove(alpm_list_t *targets) } /* Step 2: prepare the transaction based on its type, targets and flags */ - if(alpm_trans_prepare(&data) == -1) { + if(alpm_trans_prepare(config->handle, &data) == -1) { + enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), - alpm_strerrorlast()); - switch(pm_errno) { + alpm_strerror(err)); + switch(err) { case PM_ERR_PKG_INVALID_ARCH: for(i = data; i; i = alpm_list_next(i)) { char *pkg = alpm_list_getdata(i); @@ -118,18 +121,18 @@ int pacman_remove(alpm_list_t *targets) depstring); free(depstring); } - FREELIST(data); break; default: break; } + FREELIST(data); retval = 1; goto cleanup; } /* Search for holdpkg in target list */ int holdpkg = 0; - for(i = alpm_trans_get_remove(); i; i = alpm_list_next(i)) { + for(i = alpm_trans_get_remove(config->handle); i; i = alpm_list_next(i)) { pmpkg_t *pkg = alpm_list_getdata(i); if(alpm_list_find_str(config->holdpkg, alpm_pkg_get_name(pkg))) { pm_printf(PM_LOG_WARNING, _("%s is designated as a HoldPkg.\n"), @@ -143,7 +146,7 @@ int pacman_remove(alpm_list_t *targets) } /* Step 3: actually perform the removal */ - alpm_list_t *pkglist = alpm_trans_get_remove(); + alpm_list_t *pkglist = alpm_trans_get_remove(config->handle); if(pkglist == NULL) { printf(_(" there is nothing to do\n")); goto cleanup; /* we are done */ @@ -162,18 +165,20 @@ int pacman_remove(alpm_list_t *targets) goto cleanup; } - if(alpm_trans_commit(NULL) == -1) { + if(alpm_trans_commit(config->handle, &data) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), - alpm_strerrorlast()); + alpm_strerror(alpm_errno(config->handle))); retval = 1; } + FREELIST(data); + /* Step 4: release transaction resources */ cleanup: if(trans_release() == -1) { retval = 1; } - return(retval); + return retval; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/sync.c b/src/pacman/sync.c index c56934b6..37b9d6e3 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -39,7 +39,8 @@ /* if keep_used != 0, then the db files which match an used syncdb * will be kept */ -static int sync_cleandb(const char *dbpath, int keep_used) { +static int sync_cleandb(const char *dbpath, int keep_used) +{ DIR *dir; struct dirent *ent; alpm_list_t *syncdbs; @@ -47,10 +48,10 @@ static int sync_cleandb(const char *dbpath, int keep_used) { dir = opendir(dbpath); if(dir == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, _("could not access database directory\n")); - return(1); + return 1; } - syncdbs = alpm_option_get_syncdbs(); + syncdbs = alpm_option_get_syncdbs(config->handle); rewinddir(dir); /* step through the directory one file at a time */ @@ -84,7 +85,7 @@ static int sync_cleandb(const char *dbpath, int keep_used) { pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove %s\n"), path); closedir(dir); - return(1); + return 1; } continue; } @@ -110,23 +111,24 @@ static int sync_cleandb(const char *dbpath, int keep_used) { pm_fprintf(stderr, PM_LOG_ERROR, _("could not remove %s\n"), path); closedir(dir); - return(1); + return 1; } } } closedir(dir); - return(0); + return 0; } -static int sync_cleandb_all(void) { +static int sync_cleandb_all(void) +{ const char *dbpath; char newdbpath[PATH_MAX]; int ret = 0; - dbpath = alpm_option_get_dbpath(); + dbpath = alpm_option_get_dbpath(config->handle); printf(_("Database directory: %s\n"), dbpath); if(!yesno(_("Do you want to remove unused repositories?"))) { - return(0); + return 0; } /* The sync dbs were previously put in dbpath/ but are now in dbpath/sync/. * We will clean everything in dbpath/ except local/, sync/ and db.lck, and @@ -137,18 +139,19 @@ static int sync_cleandb_all(void) { ret += sync_cleandb(newdbpath, 1); printf(_("Database directory cleaned up\n")); - return(ret); + return ret; } static int sync_cleancache(int level) { alpm_list_t *i; - alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); - pmdb_t *db_local = alpm_option_get_localdb(); + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(config->handle); + pmdb_t *db_local = alpm_option_get_localdb(config->handle); + alpm_list_t *cachedirs = alpm_option_get_cachedirs(config->handle); int ret = 0; - for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { - printf(_("Cache directory: %s\n"), (char*)alpm_list_getdata(i)); + for(i = cachedirs; i; i = alpm_list_next(i)) { + printf(_("Cache directory: %s\n"), (char *)alpm_list_getdata(i)); } if(!config->cleanmethod) { @@ -165,17 +168,17 @@ static int sync_cleancache(int level) printf(_(" All current sync database packages\n")); } if(!yesno(_("Do you want to remove all other packages from cache?"))) { - return(0); + return 0; } printf(_("removing old packages from cache...\n")); } else { if(!noyes(_("Do you want to remove ALL files from cache?"))) { - return(0); + return 0; } printf(_("removing all files from cache...\n")); } - for(i = alpm_option_get_cachedirs(); i; i = alpm_list_next(i)) { + for(i = cachedirs; i; i = alpm_list_next(i)) { const char *cachedir = alpm_list_getdata(i); DIR *dir = opendir(cachedir); struct dirent *ent; @@ -191,10 +194,10 @@ static int sync_cleancache(int level) /* step through the directory one file at a time */ while((ent = readdir(dir)) != NULL) { char path[PATH_MAX]; + size_t pathlen; int delete = 1; pmpkg_t *localpkg = NULL, *pkg = NULL; const char *local_name, *local_version; - alpm_list_t *j; if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { continue; @@ -208,11 +211,19 @@ static int sync_cleancache(int level) continue; } + /* we handle .sig files with packages, not separately */ + pathlen = strlen(path); + if(strcmp(path + pathlen - 4, ".sig") == 0) { + continue; + } + /* attempt to load the package, prompt removal on failures as we may have * files here that aren't valid packages. we also don't need a full * load of the package, just the metadata. */ - if(alpm_pkg_load(path, 0, &localpkg) != 0 || localpkg == NULL) { - if(yesno(_("File %s does not seem to be a valid package, remove it?"), path)) { + if(alpm_pkg_load(config->handle, path, 0, PM_PGP_VERIFY_NEVER, &localpkg) != 0 + || localpkg == NULL) { + if(yesno(_("File %s does not seem to be a valid package, remove it?"), + path)) { if(localpkg) { alpm_pkg_free(localpkg); } @@ -235,6 +246,7 @@ static int sync_cleancache(int level) } } if(config->cleanmethod & PM_CLEAN_KEEPCUR) { + alpm_list_t *j; /* check if this package is in a sync DB */ for(j = sync_dbs; j && delete; j = alpm_list_next(j)) { pmdb_t *db = alpm_list_getdata(j); @@ -253,12 +265,17 @@ static int sync_cleancache(int level) if(delete) { unlink(path); + /* unlink a signature file if present too */ + if(PATH_MAX - 5 >= pathlen) { + strcpy(path + pathlen, ".sig"); + unlink(path); + } } } closedir(dir); } - return(ret); + return ret; } static int sync_synctree(int level, alpm_list_t *syncs) @@ -267,7 +284,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) int success = 0, ret; if(trans_init(0) == -1) { - return(0); + return 0; } for(i = syncs; i; i = alpm_list_next(i)) { @@ -276,7 +293,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) ret = alpm_db_update((level < 2 ? 0 : 1), db); if(ret < 0) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to update %s (%s)\n"), - alpm_db_get_name(db), alpm_strerrorlast()); + alpm_db_get_name(db), alpm_strerror(alpm_errno(config->handle))); } else if(ret == 1) { printf(_(" %s is up to date\n"), alpm_db_get_name(db)); success++; @@ -286,7 +303,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) } if(trans_release() == -1) { - return(0); + return 0; } /* We should always succeed if at least one DB was upgraded - we may possibly * fail later with unresolved deps, but that should be rare, and would be @@ -295,7 +312,7 @@ static int sync_synctree(int level, alpm_list_t *syncs) if(!success) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to synchronize any databases\n")); } - return(success > 0); + return (success > 0); } static void print_installed(pmdb_t *db_local, pmpkg_t *pkg) @@ -319,7 +336,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) alpm_list_t *i, *j, *ret; int freelist; int found = 0; - pmdb_t *db_local = alpm_option_get_localdb(); + pmdb_t *db_local = alpm_option_get_localdb(config->handle); for(i = syncs; i; i = alpm_list_next(i)) { pmdb_t *db = alpm_list_getdata(i); @@ -340,22 +357,14 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) alpm_list_t *grp; pmpkg_t *pkg = alpm_list_getdata(j); - if (!config->quiet) { + 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)); } - /* print the package size with the output if ShowSize option set */ - if(!config->quiet && config->showsize) { - /* Convert byte size to MB */ - double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - - printf(" [%.2f MB]", mbsize); - } - - if (!config->quiet) { + if(!config->quiet) { if((grp = alpm_pkg_get_groups(pkg)) != NULL) { alpm_list_t *k; printf(" ("); @@ -384,7 +393,7 @@ static int sync_search(alpm_list_t *syncs, alpm_list_t *targets) } } - return(!found); + return !found; } static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) @@ -432,7 +441,7 @@ static int sync_group(int level, alpm_list_t *syncs, alpm_list_t *targets) } } - return(0); + return 0; } static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) @@ -466,14 +475,14 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) if(!db) { pm_fprintf(stderr, PM_LOG_ERROR, _("repository '%s' does not exist\n"), repo); - return(1); + return 1; } for(k = alpm_db_get_pkgcache(db); k; k = alpm_list_next(k)) { pmpkg_t *pkg = alpm_list_getdata(k); if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { - dump_pkg_sync(pkg, alpm_db_get_name(db), config->op_s_info); + dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1); foundpkg = 1; break; } @@ -494,7 +503,7 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) pmpkg_t *pkg = alpm_list_getdata(k); if(strcmp(alpm_pkg_get_name(pkg), pkgstr) == 0) { - dump_pkg_sync(pkg, alpm_db_get_name(db), config->op_s_info); + dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1); foundpkg = 1; break; } @@ -512,18 +521,19 @@ static int sync_info(alpm_list_t *syncs, alpm_list_t *targets) pmdb_t *db = alpm_list_getdata(i); for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { - dump_pkg_sync(alpm_list_getdata(j), alpm_db_get_name(db), config->op_s_info); + pmpkg_t *pkg = alpm_list_getdata(j); + dump_pkg_full(pkg, PKG_FROM_SYNCDB, config->op_s_info > 1); } } } - return(ret); + return ret; } static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) { alpm_list_t *i, *j, *ls = NULL; - pmdb_t *db_local = alpm_option_get_localdb(); + pmdb_t *db_local = alpm_option_get_localdb(config->handle); if(targets) { for(i = targets; i; i = alpm_list_next(i)) { @@ -543,7 +553,7 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) pm_fprintf(stderr, PM_LOG_ERROR, _("repository \"%s\" was not found.\n"),repo); alpm_list_free(ls); - return(1); + return 1; } ls = alpm_list_add(ls, db); @@ -558,7 +568,7 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) for(j = alpm_db_get_pkgcache(db); j; j = alpm_list_next(j)) { pmpkg_t *pkg = alpm_list_getdata(j); - if (!config->quiet) { + if(!config->quiet) { printf("%s %s %s", alpm_db_get_name(db), alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); print_installed(db_local, pkg); @@ -573,12 +583,13 @@ static int sync_list(alpm_list_t *syncs, alpm_list_t *targets) alpm_list_free(ls); } - return(0); + return 0; } static alpm_list_t *syncfirst(void) { alpm_list_t *i, *res = NULL; - pmdb_t *db_local = alpm_option_get_localdb(); + pmdb_t *db_local = alpm_option_get_localdb(config->handle); + alpm_list_t *syncdbs = alpm_option_get_syncdbs(config->handle); for(i = config->syncfirst; i; i = alpm_list_next(i)) { char *pkgname = alpm_list_getdata(i); @@ -587,43 +598,44 @@ static alpm_list_t *syncfirst(void) { continue; } - if(alpm_sync_newversion(pkg, alpm_option_get_syncdbs())) { + if(alpm_sync_newversion(pkg, syncdbs)) { res = alpm_list_add(res, strdup(pkgname)); } } - return(res); + return res; } static pmdb_t *get_db(const char *dbname) { alpm_list_t *i; - for(i = alpm_option_get_syncdbs(); i; i = i->next) { + for(i = alpm_option_get_syncdbs(config->handle); i; i = i->next) { pmdb_t *db = i->data; if(strcmp(alpm_db_get_name(db), dbname) == 0) { - return(db); + return db; } } - return(NULL); + return NULL; } static int process_pkg(pmpkg_t *pkg) { - int ret = alpm_add_pkg(pkg); + int ret = alpm_add_pkg(config->handle, pkg); if(ret == -1) { - if(pm_errno == PM_ERR_TRANS_DUP_TARGET - || pm_errno == PM_ERR_PKG_IGNORED) { + enum _pmerrno_t err = alpm_errno(config->handle); + if(err == PM_ERR_TRANS_DUP_TARGET + || err == PM_ERR_PKG_IGNORED) { /* just skip duplicate or ignored targets */ pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), alpm_pkg_get_name(pkg)); - return(0); + return 0; } else { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", alpm_pkg_get_name(pkg), - alpm_strerrorlast()); - return(1); + alpm_strerror(err)); + return 1; } } - return(0); + return 0; } static int process_group(alpm_list_t *dbs, char *group) @@ -635,7 +647,7 @@ static int process_group(alpm_list_t *dbs, char *group) if(!count) { pm_fprintf(stderr, PM_LOG_ERROR, _("target not found: %s\n"), group); - return(1); + return 1; } @@ -669,25 +681,26 @@ static int process_group(alpm_list_t *dbs, char *group) } cleanup: alpm_list_free(pkgs); - return(ret); + return ret; } static int process_targname(alpm_list_t *dblist, char *targname) { - pmpkg_t *pkg = alpm_find_dbs_satisfier(dblist, targname); + pmpkg_t *pkg = alpm_find_dbs_satisfier(config->handle, dblist, targname); - /* #FS23342 - skip ignored packages when user says no */ - if(pm_errno == PM_ERR_PKG_IGNORED) { + /* #FS#23342 - skip ignored packages when user says no */ + if(alpm_errno(config->handle) == PM_ERR_PKG_IGNORED) { pm_printf(PM_LOG_WARNING, _("skipping target: %s\n"), targname); - pm_errno = 0; - return(0); + /* TODO how to do this, we shouldn't be fucking with it from the frontend */ + /* pm_errno = 0; */ + return 0; } if(pkg) { - return(process_pkg(pkg)); + return process_pkg(pkg); } /* fallback on group */ - return(process_group(dblist, targname)); + return process_group(dblist, targname); } static int process_target(char *target) @@ -717,12 +730,12 @@ static int process_target(char *target) alpm_list_free(dblist); } else { targname = targstring; - dblist = alpm_option_get_syncdbs(); + dblist = alpm_option_get_syncdbs(config->handle); ret = process_targname(dblist, targname); } cleanup: free(targstring); - return(ret); + return ret; } static int sync_trans(alpm_list_t *targets) @@ -734,7 +747,7 @@ static int sync_trans(alpm_list_t *targets) /* Step 1: create a new transaction... */ if(trans_init(config->flags) == -1) { - return(1); + return 1; } /* process targets */ @@ -748,19 +761,20 @@ static int sync_trans(alpm_list_t *targets) if(config->op_s_upgrade) { printf(_(":: Starting full system upgrade...\n")); - alpm_logaction("starting full system upgrade\n"); - if(alpm_sync_sysupgrade(config->op_s_upgrade >= 2) == -1) { - pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerrorlast()); + alpm_logaction(config->handle, "starting full system upgrade\n"); + if(alpm_sync_sysupgrade(config->handle, config->op_s_upgrade >= 2) == -1) { + pm_fprintf(stderr, PM_LOG_ERROR, "%s\n", alpm_strerror(alpm_errno(config->handle))); retval = 1; goto cleanup; } } /* Step 2: "compute" the transaction based on targets and flags */ - if(alpm_trans_prepare(&data) == -1) { + if(alpm_trans_prepare(config->handle, &data) == -1) { + enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), - alpm_strerrorlast()); - switch(pm_errno) { + alpm_strerror(err)); + switch(err) { alpm_list_t *i; case PM_ERR_PKG_INVALID_ARCH: for(i = data; i; i = alpm_list_next(i)) { @@ -799,7 +813,7 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - packages = alpm_trans_get_add(); + packages = alpm_trans_get_add(config->handle); if(packages == NULL) { /* nothing to do: just exit without complaining */ printf(_(" there is nothing to do\n")); @@ -812,8 +826,8 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - display_targets(alpm_trans_get_remove(), 0); - display_targets(alpm_trans_get_add(), 1); + display_targets(alpm_trans_get_remove(config->handle), 0); + display_targets(alpm_trans_get_add(config->handle), 1); printf("\n"); int confirm; @@ -826,10 +840,11 @@ static int sync_trans(alpm_list_t *targets) goto cleanup; } - if(alpm_trans_commit(&data) == -1) { + if(alpm_trans_commit(config->handle, &data) == -1) { + enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), - alpm_strerrorlast()); - switch(pm_errno) { + alpm_strerror(err)); + switch(err) { alpm_list_t *i; case PM_ERR_FILE_CONFLICTS: for(i = data; i; i = alpm_list_next(i)) { @@ -874,7 +889,7 @@ cleanup: retval = 1; } - return(retval); + return retval; } int pacman_sync(alpm_list_t *targets) @@ -886,7 +901,7 @@ int pacman_sync(alpm_list_t *targets) int ret = 0; if(trans_init(0) == -1) { - return(1); + return 1; } ret += sync_cleancache(config->op_s_clean); @@ -897,55 +912,55 @@ int pacman_sync(alpm_list_t *targets) ret++; } - return(ret); + return ret; } /* ensure we have at least one valid sync db set up */ - sync_dbs = alpm_option_get_syncdbs(); + sync_dbs = alpm_option_get_syncdbs(config->handle); if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) { pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n")); - return(1); + return 1; } if(config->op_s_sync) { /* grab a fresh package list */ printf(_(":: Synchronizing package databases...\n")); - alpm_logaction("synchronizing package lists\n"); + alpm_logaction(config->handle, "synchronizing package lists\n"); if(!sync_synctree(config->op_s_sync, sync_dbs)) { - return(1); + return 1; } } /* search for a package */ if(config->op_s_search) { - return(sync_search(sync_dbs, targets)); + return sync_search(sync_dbs, targets); } /* look for groups */ if(config->group) { - return(sync_group(config->group, sync_dbs, targets)); + return sync_group(config->group, sync_dbs, targets); } /* get package info */ if(config->op_s_info) { - return(sync_info(sync_dbs, targets)); + return sync_info(sync_dbs, targets); } /* get a listing of files in sync DBs */ if(config->op_q_list) { - return(sync_list(sync_dbs, targets)); + return sync_list(sync_dbs, targets); } if(targets == NULL) { if(config->op_s_upgrade) { /* proceed */ } else if(config->op_s_sync) { - return(0); + return 0; } else { /* don't proceed here unless we have an operation that doesn't require a * target list */ pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); - return(1); + return 1; } } @@ -980,7 +995,7 @@ int pacman_sync(alpm_list_t *targets) int ret = sync_trans(targs); FREELIST(targs); - return(ret); + return ret; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c index 8cd29da0..c0466456 100644 --- a/src/pacman/upgrade.c +++ b/src/pacman/upgrade.c @@ -42,22 +42,23 @@ int pacman_upgrade(alpm_list_t *targets) { alpm_list_t *i, *data = NULL; + pgp_verify_t check_sig = alpm_option_get_default_sigverify(config->handle); int retval = 0; if(targets == NULL) { pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); - return(1); + return 1; } /* Check for URL targets and process them */ for(i = targets; i; i = alpm_list_next(i)) { if(strstr(i->data, "://")) { - char *str = alpm_fetch_pkgurl(i->data); + char *str = alpm_fetch_pkgurl(config->handle, i->data); if(str == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", - (char *)i->data, alpm_strerrorlast()); - return(1); + (char *)i->data, alpm_strerror(alpm_errno(config->handle))); + return 1; } else { free(i->data); i->data = str; @@ -67,7 +68,7 @@ int pacman_upgrade(alpm_list_t *targets) /* Step 1: create a new transaction */ if(trans_init(config->flags) == -1) { - return(1); + return 1; } /* add targets to the created transaction */ @@ -75,27 +76,28 @@ int pacman_upgrade(alpm_list_t *targets) char *targ = alpm_list_getdata(i); pmpkg_t *pkg; - if(alpm_pkg_load(targ, 1, &pkg) != 0) { + if(alpm_pkg_load(config->handle, targ, 1, check_sig, &pkg) != 0) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", - targ, alpm_strerrorlast()); + targ, alpm_strerror(alpm_errno(config->handle))); trans_release(); - return(1); + return 1; } - if(alpm_add_pkg(pkg) == -1) { + if(alpm_add_pkg(config->handle, pkg) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", - targ, alpm_strerrorlast()); + targ, alpm_strerror(alpm_errno(config->handle))); alpm_pkg_free(pkg); trans_release(); - return(1); + return 1; } } /* Step 2: "compute" the transaction based on targets and flags */ /* TODO: No, compute nothing. This is stupid. */ - if(alpm_trans_prepare(&data) == -1) { + if(alpm_trans_prepare(config->handle, &data) == -1) { + enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), - alpm_strerrorlast()); - switch(pm_errno) { + alpm_strerror(err)); + switch(err) { case PM_ERR_PKG_INVALID_ARCH: for(i = data; i; i = alpm_list_next(i)) { char *pkg = alpm_list_getdata(i); @@ -135,37 +137,38 @@ int pacman_upgrade(alpm_list_t *targets) } trans_release(); FREELIST(data); - return(1); + return 1; } /* Step 3: perform the installation */ + alpm_list_t *packages = alpm_trans_get_add(config->handle); if(config->print) { - print_packages(alpm_trans_get_add()); + print_packages(packages); trans_release(); - return(0); + return 0; } /* print targets and ask user confirmation */ - alpm_list_t *packages = alpm_trans_get_add(); if(packages == NULL) { /* we are done */ printf(_(" there is nothing to do\n")); trans_release(); - return(retval); + return retval; } - display_targets(alpm_trans_get_remove(), 0); - display_targets(alpm_trans_get_add(), 1); + display_targets(alpm_trans_get_remove(config->handle), 0); + display_targets(alpm_trans_get_add(config->handle), 1); printf("\n"); int confirm = yesno(_("Proceed with installation?")); if(!confirm) { trans_release(); - return(retval); + return retval; } - if(alpm_trans_commit(&data) == -1) { + if(alpm_trans_commit(config->handle, &data) == -1) { + enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), - alpm_strerrorlast()); - switch(pm_errno) { + alpm_strerror(err)); + switch(err) { alpm_list_t *i; case PM_ERR_FILE_CONFLICTS: for(i = data; i; i = alpm_list_next(i)) { @@ -197,13 +200,13 @@ int pacman_upgrade(alpm_list_t *targets) } FREELIST(data); trans_release(); - return(1); + return 1; } if(trans_release() == -1) { retval = 1; } - return(retval); + return retval; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/util.c b/src/pacman/util.c index f695ffba..5d666e21 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -31,12 +31,14 @@ #include <stdint.h> /* intmax_t */ #include <string.h> #include <errno.h> -#include <fcntl.h> #include <ctype.h> #include <dirent.h> #include <unistd.h> #include <limits.h> #include <wchar.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> /* tcflush */ +#endif #include <alpm.h> #include <alpm_list.h> @@ -51,55 +53,69 @@ int trans_init(pmtransflag_t flags) { int ret; if(config->print) { - ret = alpm_trans_init(flags, NULL, NULL, NULL); + ret = alpm_trans_init(config->handle, flags, NULL, NULL, NULL); } else { - ret = alpm_trans_init(flags, cb_trans_evt, cb_trans_conv, + ret = alpm_trans_init(config->handle, flags, cb_trans_evt, cb_trans_conv, cb_trans_progress); } if(ret == -1) { + enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to init transaction (%s)\n"), - alpm_strerrorlast()); - if(pm_errno == PM_ERR_HANDLE_LOCK) { + alpm_strerror(err)); + if(err == PM_ERR_HANDLE_LOCK) { fprintf(stderr, _(" if you're sure a package manager is not already\n" - " running, you can remove %s\n"), alpm_option_get_lockfile()); + " running, you can remove %s\n"), + alpm_option_get_lockfile(config->handle)); } - else if(pm_errno == PM_ERR_DB_VERSION) { + else if(err == PM_ERR_DB_VERSION) { fprintf(stderr, _(" try running pacman-db-upgrade\n")); } - return(-1); + return -1; } - return(0); + return 0; } int trans_release(void) { - if(alpm_trans_release() == -1) { + if(alpm_trans_release(config->handle) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to release transaction (%s)\n"), - alpm_strerrorlast()); - return(-1); + alpm_strerror(alpm_errno(config->handle))); + return -1; } - return(0); + return 0; } int needs_root(void) { switch(config->op) { case PM_OP_DATABASE: - return(1); + return 1; case PM_OP_UPGRADE: case PM_OP_REMOVE: - return(!config->print); + return !config->print; case PM_OP_SYNC: - return(config->op_s_clean || config->op_s_sync || + return (config->op_s_clean || config->op_s_sync || (!config->group && !config->op_s_info && !config->op_q_list && !config->op_s_search && !config->print)); default: - return(0); + return 0; } } +/* discard unhandled input on the terminal's input buffer */ +static int flush_term_input(void) { +#ifdef HAVE_TCFLUSH + if(isatty(fileno(stdin))) { + return tcflush(fileno(stdin), TCIFLUSH); + } +#endif + + /* fail silently */ + return 0; +} + /* gets the current screen column width */ int getcols(int def) { @@ -125,24 +141,24 @@ int rmrf(const char *path) DIR *dirp; if(!unlink(path)) { - return(0); + return 0; } else { if(errno == ENOENT) { - return(0); + return 0; } else if(errno == EPERM) { /* fallthrough */ } else if(errno == EISDIR) { /* fallthrough */ } else if(errno == ENOTDIR) { - return(1); + return 1; } else { /* not a directory */ - return(1); + return 1; } dirp = opendir(path); if(!dirp) { - return(1); + return 1; } for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { if(dp->d_ino) { @@ -157,7 +173,7 @@ int rmrf(const char *path) if(rmdir(path)) { errflag++; } - return(errflag); + return errflag; } } @@ -170,9 +186,9 @@ const char *mbasename(const char *path) { const char *last = strrchr(path, '/'); if(last) { - return(last + 1); + return last + 1; } - return(path); + return path; } /** Parse the dirname of a program from a path. @@ -187,7 +203,7 @@ char *mdirname(const char *path) /* null or empty path */ if(path == NULL || path == '\0') { - return(strdup(".")); + return strdup("."); } ret = strdup(path); @@ -196,11 +212,11 @@ char *mdirname(const char *path) if(last != NULL) { /* we found a '/', so terminate our string */ *last = '\0'; - return(ret); + return ret; } /* no slash found */ free(ret); - return(strdup(".")); + return strdup("."); } /* output a string, but wrap words properly with a specified indentation @@ -286,7 +302,7 @@ char *strtrim(char *str) if(str == NULL || *str == '\0') { /* string is empty, so we're done. */ - return(str); + return str; } while(isspace((unsigned char)*pch)) { @@ -298,7 +314,7 @@ char *strtrim(char *str) /* check if there wasn't anything but whitespace in the string. */ if(*str == '\0') { - return(str); + return str; } pch = (str + (strlen(str) - 1)); @@ -307,7 +323,7 @@ char *strtrim(char *str) } *++pch = '\0'; - return(str); + return str; } /* Replace all occurances of 'needle' with 'replace' in 'str', returning @@ -321,7 +337,7 @@ char *strreplace(const char *str, const char *needle, const char *replace) size_t newsz; if(!str) { - return(NULL); + return NULL; } p = str; @@ -334,7 +350,7 @@ char *strreplace(const char *str, const char *needle, const char *replace) /* no occurences of needle found */ if(!list) { - return(strdup(str)); + return strdup(str); } /* size of new string = size of old string + "number of occurences of needle" * x "size difference between replace and needle" */ @@ -342,7 +358,7 @@ char *strreplace(const char *str, const char *needle, const char *replace) alpm_list_count(list) * (replacesz - needlesz); newstr = malloc(newsz); if(!newstr) { - return(NULL); + return NULL; } *newstr = '\0'; @@ -368,7 +384,7 @@ char *strreplace(const char *str, const char *needle, const char *replace) } *newp = '\0'; - return(newstr); + return newstr; } /** Splits a string into a list of strings using the chosen character as @@ -388,7 +404,7 @@ alpm_list_t *strsplit(const char *str, const char splitchar) while((str = strchr(str, splitchar))) { dup = strndup(prev, (size_t)(str - prev)); if(dup == NULL) { - return(NULL); + return NULL; } list = alpm_list_add(list, dup); @@ -398,11 +414,11 @@ alpm_list_t *strsplit(const char *str, const char splitchar) dup = strdup(prev); if(dup == NULL) { - return(NULL); + return NULL; } list = alpm_list_add(list, dup); - return(list); + return list; } static int string_length(const char *s) @@ -411,7 +427,7 @@ static int string_length(const char *s) wchar_t *wcstr; if(!s) { - return(0); + return 0; } /* len goes from # bytes -> # chars -> # cols */ len = strlen(s) + 1; @@ -420,7 +436,7 @@ static int string_length(const char *s) len = wcswidth(wcstr, len); free(wcstr); - return(len); + return len; } void string_display(const char *title, const char *string) @@ -438,6 +454,117 @@ void string_display(const char *title, const char *string) printf("\n"); } +static void table_print_line(const alpm_list_t *line, + const alpm_list_t *formats) +{ + const alpm_list_t *curformat = formats; + const alpm_list_t *curcell = line; + + while(curcell && curformat) { + printf(alpm_list_getdata(curformat), alpm_list_getdata(curcell)); + curcell = alpm_list_next(curcell); + curformat = alpm_list_next(curformat); + } + + printf("\n"); +} + +/* creates format strings by checking max cell lengths in cols */ +static alpm_list_t *table_create_format(const alpm_list_t *header, + const alpm_list_t *rows) +{ + alpm_list_t *longest_str, *longest_strs = NULL; + alpm_list_t *formats = NULL; + const alpm_list_t *i, *row, *cell; + char *str, *formatstr; + const int padding = 2; + int colwidth, totalwidth = 0; + int curcol = 0; + + /* header determines column count and initial values of longest_strs */ + for(i = header; i; i = alpm_list_next(i)) { + longest_strs = alpm_list_add(longest_strs, alpm_list_getdata(i)); + } + + /* now find the longest string in each column */ + for(longest_str = longest_strs; longest_str; + longest_str = alpm_list_next(longest_str), curcol++) { + for(i = rows; i; i = alpm_list_next(i)) { + row = alpm_list_getdata(i); + cell = alpm_list_nth(row, curcol); + str = alpm_list_getdata(cell); + + if(strlen(str) > strlen(alpm_list_getdata(longest_str))) { + longest_str->data = str; + } + } + } + + /* now use the column width info to generate format strings */ + for(i = longest_strs; i; i = alpm_list_next(i)) { + const char *display; + colwidth = strlen(alpm_list_getdata(i)) + padding; + totalwidth += colwidth; + + /* right align the last column for a cleaner table display */ + display = (alpm_list_next(i) != NULL) ? "%%-%ds" : "%%%ds"; + pm_asprintf(&formatstr, display, colwidth); + + formats = alpm_list_add(formats, formatstr); + } + + alpm_list_free(longest_strs); + + /* return NULL if terminal is not wide enough */ + if(totalwidth > getcols(80)) { + pm_fprintf(stderr, PM_LOG_WARNING, _("insufficient columns available for table display\n")); + FREELIST(formats); + return NULL; + } + + return formats; +} + +/** Displays the list in table format + * + * @param title the tables title + * @param header the column headers. column count is determined by the nr + * 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) + * + * @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) +{ + const alpm_list_t *i; + alpm_list_t *formats; + + if(rows == NULL || header == NULL) { + return 0; + } + + formats = table_create_format(header, rows); + if(formats == NULL) { + return -1; + } + + if(title != NULL) { + printf("%s\n\n", title); + } + + table_print_line(header, formats); + printf("\n"); + + for(i = rows; i; i = alpm_list_next(i)) { + table_print_line(alpm_list_getdata(i), formats); + } + + FREELIST(formats); + return 0; +} + void list_display(const char *title, const alpm_list_t *list) { const alpm_list_t *i; @@ -467,7 +594,7 @@ void list_display(const char *title, const alpm_list_t *list) for (j = 1; j <= len; j++) { printf(" "); } - } else if (cols != len) { + } else if(cols != len) { /* 2 spaces are added if this is not the first element on a line. */ printf(" "); cols += 2; @@ -506,100 +633,215 @@ void list_display_linebreak(const char *title, const alpm_list_t *list) } } } + +/* creates a header row for use with table_display */ +static alpm_list_t *create_verbose_header(int install) +{ + alpm_list_t *res = NULL; + char *str; + + pm_asprintf(&str, "%s", _("Name")); + res = alpm_list_add(res, str); + pm_asprintf(&str, "%s", _("Old Version")); + res = alpm_list_add(res, str); + if(install) { + pm_asprintf(&str, "%s", _("New Version")); + res = alpm_list_add(res, str); + } + pm_asprintf(&str, "%s", _("Size")); + res = alpm_list_add(res, str); + + return res; +} + +/* returns package info as list of strings */ +static alpm_list_t *create_verbose_row(pmpkg_t *pkg, int install) +{ + char *str; + double size; + const char *label; + alpm_list_t *ret = NULL; + pmdb_t *ldb = alpm_option_get_localdb(config->handle); + + /* a row consists of the package name, */ + pm_asprintf(&str, "%s", alpm_pkg_get_name(pkg)); + ret = alpm_list_add(ret, str); + + /* old and new versions */ + if(install) { + pmpkg_t *oldpkg = alpm_db_get_pkg(ldb, alpm_pkg_get_name(pkg)); + pm_asprintf(&str, "%s", + oldpkg != NULL ? alpm_pkg_get_version(oldpkg) : ""); + ret = alpm_list_add(ret, str); + } + + pm_asprintf(&str, "%s", alpm_pkg_get_version(pkg)); + ret = alpm_list_add(ret, str); + + /* and size */ + size = humanize_size(alpm_pkg_get_size(pkg), 'M', 1, &label); + pm_asprintf(&str, "%.2f %s", size, label); + ret = alpm_list_add(ret, str); + + return ret; +} + /* prepare a list of pkgs to display */ void display_targets(const alpm_list_t *pkgs, int install) { char *str; + const char *title, *label; + double size; const alpm_list_t *i; - off_t isize = 0, dlsize = 0; - double mbisize = 0.0, mbdlsize = 0.0; - alpm_list_t *targets = NULL; + off_t isize = 0, rsize = 0, dlsize = 0; + alpm_list_t *j, *lp, *header = NULL, *targets = NULL; + pmdb_t *db_local = alpm_option_get_localdb(config->handle); if(!pkgs) { return; } - printf("\n"); + /* gather pkg infos */ for(i = pkgs; i; i = alpm_list_next(i)) { pmpkg_t *pkg = alpm_list_getdata(i); if(install) { + pmpkg_t *lpkg = alpm_db_get_pkg(db_local, alpm_pkg_get_name(pkg)); dlsize += alpm_pkg_download_size(pkg); + if(lpkg) { + /* add up size of all removed packages */ + rsize += alpm_pkg_get_isize(lpkg); + } } isize += alpm_pkg_get_isize(pkg); - /* print the package size with the output if ShowSize option set */ - if(config->showsize) { - double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - - pm_asprintf(&str, "%s-%s [%.2f MB]", alpm_pkg_get_name(pkg), - alpm_pkg_get_version(pkg), mbsize); + if(config->verbosepkglists) { + targets = alpm_list_add(targets, create_verbose_row(pkg, install)); } else { pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); + targets = alpm_list_add(targets, str); } - targets = alpm_list_add(targets, str); } - /* Convert byte sizes to MB */ - mbdlsize = (double)dlsize / (1024.0 * 1024.0); - mbisize = (double)isize / (1024.0 * 1024.0); + /* print to screen */ + title = install ? _("Targets (%d):") : _("Remove (%d):"); + pm_asprintf(&str, title, alpm_list_count(pkgs)); - if(install) { - pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets)); + printf("\n"); + if(config->verbosepkglists) { + header = create_verbose_header(install); + if(table_display(str, header, targets) != 0) { + config->verbosepkglists = 0; + display_targets(pkgs, install); + goto out; + } + } else { list_display(str, targets); - free(str); - printf("\n"); + } + printf("\n"); - printf(_("Total Download Size: %.2f MB\n"), mbdlsize); + if(install) { + size = humanize_size(dlsize, 'M', 1, &label); + printf(_("Total Download Size: %.2f %s\n"), size, label); if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY)) { - printf(_("Total Installed Size: %.2f MB\n"), mbisize); + size = humanize_size(isize, 'M', 1, &label); + printf(_("Total Installed Size: %.2f %s\n"), size, label); + /* only show this net value if different from raw installed size */ + if(rsize > 0) { + size = humanize_size(isize - rsize, 'M', 1, &label); + printf(_("Net Upgrade Size: %.2f %s\n"), size, label); + } } } else { - pm_asprintf(&str, _("Remove (%d):"), alpm_list_count(targets)); - list_display(str, targets); - free(str); - printf("\n"); - - printf(_("Total Removed Size: %.2f MB\n"), mbisize); + size = humanize_size(isize, 'M', 1, &label); + printf(_("Total Removed Size: %.2f %s\n"), size, label); } - FREELIST(targets); +out: + /* cleanup */ + if(config->verbosepkglists) { + /* targets is a list of lists of strings, free inner lists here */ + for(j = alpm_list_first(targets); j; j = alpm_list_next(j)) { + lp = alpm_list_getdata(j); + FREELIST(lp); + } + alpm_list_free(targets); + FREELIST(header); + } else { + FREELIST(targets); + } + free(str); } static off_t pkg_get_size(pmpkg_t *pkg) { switch(config->op) { case PM_OP_SYNC: - return(alpm_pkg_download_size(pkg)); + return alpm_pkg_download_size(pkg); case PM_OP_UPGRADE: - return(alpm_pkg_get_size(pkg)); + return alpm_pkg_get_size(pkg); default: - return(alpm_pkg_get_isize(pkg)); + return alpm_pkg_get_isize(pkg); } } static char *pkg_get_location(pmpkg_t *pkg) { - pmdb_t *db; - const char *dburl; - char *string; + alpm_list_t *servers; + char *string = NULL; switch(config->op) { case PM_OP_SYNC: - db = alpm_pkg_get_db(pkg); - dburl = alpm_db_get_url(db); - if(dburl) { - char *pkgurl = NULL; - pm_asprintf(&pkgurl, "%s/%s", dburl, alpm_pkg_get_filename(pkg)); - return(pkgurl); + servers = alpm_db_get_servers(alpm_pkg_get_db(pkg)); + if(servers) { + pm_asprintf(&string, "%s/%s", alpm_list_getdata(servers), + alpm_pkg_get_filename(pkg)); + return string; } case PM_OP_UPGRADE: - return(strdup(alpm_pkg_get_filename(pkg))); + return strdup(alpm_pkg_get_filename(pkg)); default: - string = NULL; pm_asprintf(&string, "%s-%s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); - return(string); + return string; + } +} + +/** Converts sizes in bytes into human readable units. + * + * @param bytes the size in bytes + * @param target_unit '\0' or a short label. If equal to one of the short unit + * labels ('B', 'K', ...) bytes is converted to target_unit; if '\0', the first + * unit which will bring the value to below a threshold of 2048 will be chosen. + * @param long_labels whether to use short ("K") or long ("KiB") unit labels + * @param label will be set to the appropriate unit label + * + * @return the size in the appropriate unit + */ +double humanize_size(off_t bytes, const char target_unit, int long_labels, + const char **label) +{ + static const char *shortlabels[] = {"B", "K", "M", "G", "T", "P"}; + static const char *longlabels[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; + static const int unitcount = sizeof(shortlabels) / sizeof(shortlabels[0]); + + const char **labels = long_labels ? longlabels : shortlabels; + double val = (double)bytes; + int index; + + for(index = 0; index < unitcount - 1; index++) { + if(target_unit != '\0' && shortlabels[index][0] == target_unit) { + break; + } else if(target_unit == '\0' && val <= 2048.0 && val >= -2048.0) { + break; + } + val /= 1024.0; } + + if(label) { + *label = labels[index]; + } + + return val; } void print_packages(const alpm_list_t *packages) @@ -660,7 +902,7 @@ void print_packages(const alpm_list_t *packages) * alpm "compare func" signature */ int str_cmp(const void *s1, const void *s2) { - return(strcmp(s1, s2)); + return strcmp(s1, s2); } void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg) @@ -729,13 +971,13 @@ static int parseindex(char *s, int *val, int min, int max) if(n < min || n > max) { fprintf(stderr, _("Invalid value: %d is not between %d and %d\n"), n, min, max); - return(-1); + return -1; } *val = n; - return(0); + return 0; } else { fprintf(stderr, _("Invalid number: %s\n"), s); - return(-1); + return -1; } } @@ -749,7 +991,7 @@ static int multiselect_parse(char *array, int count, char *response) char *ends = NULL; char *starts = strtok_r(str, " ", &saveptr); - if (starts == NULL) { + if(starts == NULL) { break; } strtrim(starts); @@ -757,7 +999,7 @@ static int multiselect_parse(char *array, int count, char *response) if(len == 0) continue; - if (*starts == '^') { + if(*starts == '^') { starts++; len--; include = 0; @@ -776,14 +1018,14 @@ static int multiselect_parse(char *array, int count, char *response) } if(parseindex(starts, &start, 1, count) != 0) - return(-1); + return -1; if(!ends) { array[start-1] = include; } else { int d; if(parseindex(ends, &end, start, count) != 0) { - return(-1); + return -1; } for(d = start; d <= end; d++) { array[d-1] = include; @@ -791,7 +1033,7 @@ static int multiselect_parse(char *array, int count, char *response) } } - return(0); + return 0; } int multiselect_question(char *array, int count) @@ -818,6 +1060,8 @@ int multiselect_question(char *array, int count) break; } + flush_term_input(); + if(fgets(response, sizeof(response), stdin)) { strtrim(response); if(strlen(response) > 0) { @@ -829,7 +1073,7 @@ int multiselect_question(char *array, int count) } break; } - return(0); + return 0; } int select_question(int count) @@ -855,19 +1099,21 @@ int select_question(int count) break; } + flush_term_input(); + if(fgets(response, sizeof(response), stdin)) { strtrim(response); if(strlen(response) > 0) { int n; if(parseindex(response, &n, 1, count) != 0) continue; - return(n-1); + return (n - 1); } } break; } - return(preset-1); + return (preset - 1); } @@ -898,23 +1144,25 @@ static int question(short preset, char *fmt, va_list args) if(config->noconfirm) { fprintf(stream, "\n"); - return(preset); + return preset; } fflush(stream); + flush_term_input(); + if(fgets(response, sizeof(response), stdin)) { strtrim(response); if(strlen(response) == 0) { - return(preset); + return preset; } if(strcasecmp(response, _("Y")) == 0 || strcasecmp(response, _("YES")) == 0) { - return(1); - } else if (strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) { - return(0); + return 1; + } else if(strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) { + return 0; } } - return(0); + return 0; } int yesno(char *fmt, ...) @@ -926,7 +1174,7 @@ int yesno(char *fmt, ...) ret = question(1, fmt, args); va_end(args); - return(ret); + return ret; } int noyes(char *fmt, ...) @@ -938,7 +1186,7 @@ int noyes(char *fmt, ...) ret = question(0, fmt, args); va_end(args); - return(ret); + return ret; } int pm_printf(pmloglevel_t level, const char *format, ...) @@ -951,7 +1199,7 @@ int pm_printf(pmloglevel_t level, const char *format, ...) ret = pm_vfprintf(stdout, level, format, args); va_end(args); - return(ret); + return ret; } int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...) @@ -964,7 +1212,7 @@ int pm_fprintf(FILE *stream, pmloglevel_t level, const char *format, ...) ret = pm_vfprintf(stream, level, format, args); va_end(args); - return(ret); + return ret; } int pm_asprintf(char **string, const char *format, ...) @@ -980,7 +1228,7 @@ int pm_asprintf(char **string, const char *format, ...) } va_end(args); - return(ret); + return ret; } int pm_vasprintf(char **string, pmloglevel_t level, const char *format, va_list args) @@ -1016,7 +1264,7 @@ int pm_vasprintf(char **string, pmloglevel_t level, const char *format, va_list } free(msg); - return(ret); + return ret; } int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list args) @@ -1064,7 +1312,7 @@ int pm_vfprintf(FILE *stream, pmloglevel_t level, const char *format, va_list ar /* print the message using va_arg list */ ret = vfprintf(stream, format, args); - return(ret); + return ret; } #ifndef HAVE_STRNDUP @@ -1073,7 +1321,7 @@ static size_t strnlen(const char *s, size_t max) { register const char *p; for(p = s; *p && max--; ++p); - return(p - s); + return (p - s); } char *strndup(const char *s, size_t n) @@ -1081,11 +1329,11 @@ char *strndup(const char *s, size_t n) size_t len = strnlen(s, n); char *new = (char *) malloc(len + 1); - if (new == NULL) + if(new == NULL) return NULL; new[len] = '\0'; - return (char *) memcpy(new, s, len); + return (char *)memcpy(new, s, len); } #endif diff --git a/src/pacman/util.h b/src/pacman/util.h index 53176fae..95c1ce92 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -52,6 +52,8 @@ char *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); +double humanize_size(off_t bytes, const char target_unit, int long_labels, 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 display_targets(const alpm_list_t *pkgs, int install); diff --git a/src/util/cleanupdelta.c b/src/util/cleanupdelta.c index 71ba3a47..98291706 100644 --- a/src/util/cleanupdelta.c +++ b/src/util/cleanupdelta.c @@ -29,9 +29,11 @@ #define BASENAME "cleanupdelta" +pmhandle_t *handle = NULL; + static void cleanup(int signum) { - if(alpm_release() == -1) { - fprintf(stderr, "error releasing alpm: %s\n", alpm_strerrorlast()); + if(handle && alpm_release(handle) == -1) { + fprintf(stderr, "error releasing alpm\n"); } exit(signum); @@ -65,7 +67,7 @@ static void checkpkgs(alpm_list_t *pkglist) } } -static void checkdbs(char *dbpath, alpm_list_t *dbnames) { +static void checkdbs(const char *dbpath, alpm_list_t *dbnames) { char syncdbpath[PATH_MAX]; pmdb_t *db = NULL; alpm_list_t *i; @@ -73,10 +75,10 @@ static void checkdbs(char *dbpath, alpm_list_t *dbnames) { for(i = dbnames; i; i = alpm_list_next(i)) { char *dbname = alpm_list_getdata(i); snprintf(syncdbpath, PATH_MAX, "%s/sync/%s", dbpath, dbname); - db = alpm_db_register_sync(dbname); + db = alpm_db_register_sync(handle, dbname); if(db == NULL) { fprintf(stderr, "error: could not register sync database (%s)\n", - alpm_strerrorlast()); + alpm_strerror(alpm_errno(handle))); return; } checkpkgs(alpm_db_get_pkgcache(db)); @@ -93,7 +95,8 @@ static void usage(void) { int main(int argc, char *argv[]) { - char *dbpath = DBPATH; + const char *dbpath = DBPATH; + enum _pmerrno_t err; int a = 1; alpm_list_t *dbnames = NULL; @@ -117,15 +120,14 @@ int main(int argc, char *argv[]) usage(); } - if(alpm_initialize() == -1) { - fprintf(stderr, "cannot initialize alpm: %s\n", alpm_strerrorlast()); - return(1); + handle = alpm_initialize(ROOTDIR, dbpath, &err); + if(!handle) { + fprintf(stderr, "cannot initialize alpm: %s\n", alpm_strerror(err)); + return 1; } /* let us get log messages from libalpm */ - alpm_option_set_logcb(output_cb); - - alpm_option_set_dbpath(dbpath); + alpm_option_set_logcb(handle, output_cb); checkdbs(dbpath,dbnames); alpm_list_free(dbnames); diff --git a/src/util/pactree.c b/src/util/pactree.c index 6a10006f..1dee61bf 100644 --- a/src/util/pactree.c +++ b/src/util/pactree.c @@ -27,63 +27,66 @@ #include <alpm_list.h> /* output */ -char *provides = " provides"; -char *unresolvable = " [unresolvable]"; -char *branch_tip1 = "|--"; -char *branch_tip2 = "+--"; -int indent_size = 3; - -/* color */ -char *branch1_color = "\033[0;33m"; /* yellow */ -char *branch2_color = "\033[0;37m"; /* white */ -char *leaf1_color = "\033[1;32m"; /* bold green */ -char *leaf2_color = "\033[0;32m"; /* green */ -char *color_off = "\033[0m"; +struct graph_style { + const char *provides; + const char *tip1; + const char *tip2; + int indent; +}; + +static struct graph_style graph_default = { + " provides", + "|--", + "+--", + 3 +}; + +static struct graph_style graph_linear = { + "", + "", + "", + 0 +}; + +/* color choices */ +struct color_choices { + const char *branch1; + const char *branch2; + const char *leaf1; + const char *leaf2; + const char *off; +}; + +static struct color_choices use_color = { + "\033[0;33m", /* yellow */ + "\033[0;37m", /* white */ + "\033[1;32m", /* bold green */ + "\033[0;32m", /* green */ + "\033[0m" +}; + +static struct color_choices no_color = { + "", + "", + "", + "", + "" +}; /* globals */ +pmhandle_t *handle = NULL; pmdb_t *db_local; alpm_list_t *walked = NULL; alpm_list_t *provisions = NULL; /* options */ -int color = 0; +struct color_choices *color = &no_color; +struct graph_style *style = &graph_default; int graphviz = 0; -int linear = 0; int max_depth = -1; int reverse = 0; int unique = 0; -char *dbpath = NULL; - -static int alpm_local_init(void) -{ - int ret; - - ret = alpm_initialize(); - if(ret != 0) { - return(ret); - } - - ret = alpm_option_set_root(ROOTDIR); - if(ret != 0) { - return(ret); - } - - if(dbpath) { - ret = alpm_option_set_dbpath(dbpath); - } else { - ret = alpm_option_set_dbpath(DBPATH); - } - if(ret != 0) { - return(ret); - } - - db_local = alpm_option_get_localdb(); - if(!db_local) { - return(1); - } - - return(0); -} +const char *dbpath = DBPATH; static int parse_options(int argc, char *argv[]) { @@ -109,10 +112,10 @@ static int parse_options(int argc, char *argv[]) switch(opt) { case 'b': - dbpath = strdup(optarg); + dbpath = optarg; break; case 'c': - color = 1; + color = &use_color; break; case 'd': /* validate depth */ @@ -126,40 +129,27 @@ static int parse_options(int argc, char *argv[]) graphviz = 1; break; case 'l': - linear = 1; + style = &graph_linear; break; case 'r': reverse = 1; break; case 'u': - unique = linear = 1; + unique = 1; + style = &graph_linear; break; case 'h': case '?': default: - return(1); + return 1; } } if(!argv[optind]) { - return(1); - } - - if(!color) { - branch1_color = ""; - branch2_color = ""; - leaf1_color = ""; - leaf2_color = ""; - color_off = ""; - } - if(linear) { - provides = ""; - branch_tip1 = ""; - branch_tip2 = ""; - indent_size = 0; + return 1; } - return(0); + return 0; } static void usage(void) @@ -178,19 +168,15 @@ static void usage(void) static void cleanup(void) { - if(dbpath) { - free(dbpath); - } - alpm_list_free(walked); alpm_list_free(provisions); - alpm_release(); + alpm_release(handle); } /* pkg provides provision */ static void print_text(const char *pkg, const char *provision, int depth) { - int indent_sz = (depth + 1) * indent_size; + int indent_sz = (depth + 1) * style->indent; if(!pkg && !provision) { /* not much we can do */ @@ -199,17 +185,17 @@ static void print_text(const char *pkg, const char *provision, int depth) if(!pkg && provision) { /* we failed to resolve provision */ - printf("%s%*s%s%s%s%s%s\n", branch1_color, indent_sz, branch_tip1, - leaf1_color, provision, branch1_color, unresolvable, color_off); + printf("%s%*s%s%s%s [unresolvable]%s\n", color->branch1, indent_sz, + style->tip1, color->leaf1, provision, color->branch1, color->off); } else if(provision && strcmp(pkg, provision) != 0) { /* pkg provides provision */ - printf("%s%*s%s%s%s%s %s%s%s\n", branch2_color, indent_sz, branch_tip2, - leaf1_color, pkg, leaf2_color, provides, leaf1_color, provision, - color_off); + printf("%s%*s%s%s%s%s %s%s%s\n", color->branch2, indent_sz, style->tip2, + color->leaf1, pkg, color->leaf2, style->provides, color->leaf1, provision, + color->off); } else { /* pkg is a normal package */ - printf("%s%*s%s%s%s\n", branch1_color, indent_sz, branch_tip1, leaf1_color, - pkg, color_off); + printf("%s%*s%s%s%s\n", color->branch1, indent_sz, style->tip1, color->leaf1, + pkg, color->off); } } @@ -267,7 +253,7 @@ static void walk_reverse_deps(pmpkg_t *pkg, int depth) return; } - walked = alpm_list_add(walked, (void*)alpm_pkg_get_name(pkg)); + walked = alpm_list_add(walked, (void *)alpm_pkg_get_name(pkg)); required_by = alpm_pkg_compute_requiredby(pkg); for(i = required_by; i; i = alpm_list_next(i)) { @@ -299,7 +285,7 @@ static void walk_deps(pmpkg_t *pkg, int depth) return; } - walked = alpm_list_add(walked, (void*)alpm_pkg_get_name(pkg)); + walked = alpm_list_add(walked, (void *)alpm_pkg_get_name(pkg)); for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { pmdepend_t *depend = alpm_list_getdata(i); @@ -328,22 +314,27 @@ static void walk_deps(pmpkg_t *pkg, int depth) int main(int argc, char *argv[]) { - int ret; + int ret = 0; + enum _pmerrno_t err; const char *target_name; pmpkg_t *pkg; - ret = parse_options(argc, argv); - if(ret != 0) { + if(parse_options(argc, argv) != 0) { usage(); + ret = 1; goto finish; } - ret = alpm_local_init(); - if(ret != 0) { - fprintf(stderr, "error: cannot initialize alpm: %s\n", alpm_strerrorlast()); + handle = alpm_initialize(ROOTDIR, dbpath, &err); + if(!handle) { + fprintf(stderr, "error: cannot initialize alpm: %s\n", + alpm_strerror(err)); + ret = 1; goto finish; } + db_local = alpm_option_get_localdb(handle); + /* we only care about the first non option arg for walking */ target_name = argv[optind]; @@ -366,7 +357,7 @@ int main(int argc, char *argv[]) finish: cleanup(); - return(ret); + return ret; } /* vim: set ts=2 sw=2 noet: */ diff --git a/src/util/testdb.c b/src/util/testdb.c index 0436a23f..0bd78202 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -31,9 +31,11 @@ #define BASENAME "testdb" +pmhandle_t *handle = NULL; + static void cleanup(int signum) { - if(alpm_release() == -1) { - fprintf(stderr, "error releasing alpm: %s\n", alpm_strerrorlast()); + if(handle && alpm_release(handle) == -1) { + fprintf(stderr, "error releasing alpm\n"); } exit(signum); @@ -59,14 +61,14 @@ static int check_localdb_files(void) int ret = 0; DIR *dir; - dbpath = alpm_option_get_dbpath(); + dbpath = alpm_option_get_dbpath(handle); snprintf(path, sizeof(path), "%slocal", dbpath); if(!(dir = opendir(path))) { fprintf(stderr, "error : %s : %s\n", path, strerror(errno)); - return(1); + return 1; } - while ((ent = readdir(dir)) != NULL) { + while((ent = readdir(dir)) != NULL) { if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 || ent->d_name[0] == '.') { continue; @@ -85,10 +87,10 @@ static int check_localdb_files(void) } if(closedir(dir)) { fprintf(stderr, "error closing dbpath : %s\n", strerror(errno)); - return(1); + return 1; } - return(ret); + return ret; } static int checkdeps(alpm_list_t *pkglist) @@ -96,7 +98,7 @@ static int checkdeps(alpm_list_t *pkglist) alpm_list_t *data, *i; int ret = 0; /* check dependencies */ - data = alpm_checkdeps(pkglist, 0, NULL, pkglist); + data = alpm_checkdeps(handle, pkglist, NULL, pkglist, 0); for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); pmdepend_t *dep = alpm_miss_get_dep(miss); @@ -107,7 +109,7 @@ static int checkdeps(alpm_list_t *pkglist) ret++; } FREELIST(data); - return(ret); + return ret; } static int checkconflicts(alpm_list_t *pkglist) @@ -115,7 +117,7 @@ static int checkconflicts(alpm_list_t *pkglist) alpm_list_t *data, *i; int ret = 0; /* check conflicts */ - data = alpm_checkconflicts(pkglist); + data = alpm_checkconflicts(handle, pkglist); for(i = data; i; i = i->next) { pmconflict_t *conflict = alpm_list_getdata(i); printf("%s conflicts with %s\n", alpm_conflict_get_package1(conflict), @@ -123,7 +125,7 @@ static int checkconflicts(alpm_list_t *pkglist) ret++; } FREELIST(data); - return(ret); + return ret; } static int check_localdb(void) { @@ -133,19 +135,14 @@ static int check_localdb(void) { ret = check_localdb_files(); if(ret) { - return(ret); + return ret; } - db = alpm_option_get_localdb(); - if(db == NULL) { - fprintf(stderr, "error: could not register 'local' database (%s)\n", - alpm_strerrorlast()); - cleanup(EXIT_FAILURE); - } + db = alpm_option_get_localdb(handle); pkglist = alpm_db_get_pkgcache(db); ret += checkdeps(pkglist); ret += checkconflicts(pkglist); - return(ret); + return ret; } static int check_syncdbs(alpm_list_t *dbnames) { @@ -155,10 +152,10 @@ static int check_syncdbs(alpm_list_t *dbnames) { for(i = dbnames; i; i = alpm_list_next(i)) { char *dbname = alpm_list_getdata(i); - db = alpm_db_register_sync(dbname); + db = alpm_db_register_sync(handle, dbname); if(db == NULL) { fprintf(stderr, "error: could not register sync database (%s)\n", - alpm_strerrorlast()); + alpm_strerror(alpm_errno(handle))); ret = 1; goto cleanup; } @@ -169,7 +166,7 @@ static int check_syncdbs(alpm_list_t *dbnames) { cleanup: alpm_list_free(syncpkglist); - return(ret); + return ret; } static void usage(void) { @@ -184,7 +181,8 @@ static void usage(void) { int main(int argc, char *argv[]) { int ret = 0; - char *dbpath = DBPATH; + enum _pmerrno_t err; + const char *dbpath = DBPATH; int a = 1; alpm_list_t *dbnames = NULL; @@ -204,18 +202,14 @@ int main(int argc, char *argv[]) a++; } - if(alpm_initialize() == -1) { - fprintf(stderr, "cannot initialize alpm: %s\n", alpm_strerrorlast()); - return(EXIT_FAILURE); + handle = alpm_initialize(ROOTDIR, dbpath, &err); + if(!handle) { + fprintf(stderr, "cannot initialize alpm: %s\n", alpm_strerror(err)); + return EXIT_FAILURE; } /* let us get log messages from libalpm */ - alpm_option_set_logcb(output_cb); - - if(alpm_option_set_dbpath(dbpath) != 0) { - fprintf(stderr, "cannot set dbpath: %s\n", alpm_strerrorlast()); - return(EXIT_FAILURE); - } + alpm_option_set_logcb(handle, output_cb); if(!dbnames) { ret = check_localdb(); diff --git a/src/util/testpkg.c b/src/util/testpkg.c index d0d9cac1..c6f02e34 100644 --- a/src/util/testpkg.c +++ b/src/util/testpkg.c @@ -40,23 +40,28 @@ static void output_cb(pmloglevel_t level, const char *fmt, va_list args) int main(int argc, char *argv[]) { int retval = 1; /* default = false */ + pmhandle_t *handle; + enum _pmerrno_t err; pmpkg_t *pkg = NULL; if(argc != 2) { fprintf(stderr, "usage: %s <package file>\n", BASENAME); - return(1); + return 1; } - if(alpm_initialize() == -1) { - fprintf(stderr, "cannot initialize alpm: %s\n", alpm_strerrorlast()); - return(1); + handle = alpm_initialize(ROOTDIR, DBPATH, &err); + if(!handle) { + fprintf(stderr, "cannot initialize alpm: %s\n", alpm_strerror(err)); + return 1; } /* let us get log messages from libalpm */ - alpm_option_set_logcb(output_cb); + alpm_option_set_logcb(handle, output_cb); - if(alpm_pkg_load(argv[1], 1, &pkg) == -1 || pkg == NULL) { - switch(pm_errno) { + if(alpm_pkg_load(handle, argv[1], 1, PM_PGP_VERIFY_OPTIONAL, &pkg) == -1 + || pkg == NULL) { + enum _pmerrno_t err = alpm_errno(handle); + switch(err) { case PM_ERR_PKG_OPEN: printf("Cannot open the given file.\n"); break; @@ -65,7 +70,7 @@ int main(int argc, char *argv[]) printf("Package is invalid.\n"); break; default: - printf("libalpm error: %s\n", alpm_strerrorlast()); + printf("libalpm error: %s\n", alpm_strerror(err)); break; } retval = 1; @@ -75,9 +80,9 @@ int main(int argc, char *argv[]) retval = 0; } - if(alpm_release() == -1) { - fprintf(stderr, "error releasing alpm: %s\n", alpm_strerrorlast()); + if(alpm_release(handle) == -1) { + fprintf(stderr, "error releasing alpm\n"); } - return(retval); + return retval; } diff --git a/src/util/vercmp.c b/src/util/vercmp.c index adb5a42a..88cf49a6 100644 --- a/src/util/vercmp.c +++ b/src/util/vercmp.c @@ -45,13 +45,13 @@ int main(int argc, char *argv[]) if(argc == 1) { usage(); - return(2); + return 2; } if(argc > 1 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "--usage") == 0)) { usage(); - return(0); + return 0; } if(argc > 2) { s2 = argv[2]; @@ -62,5 +62,5 @@ int main(int argc, char *argv[]) ret = alpm_pkg_vercmp(s1, s2); printf("%d\n", ret); - return(EXIT_SUCCESS); + return EXIT_SUCCESS; } diff --git a/test/pacman/pactest.py b/test/pacman/pactest.py index 69e655a0..77f87da6 100755 --- a/test/pacman/pactest.py +++ b/test/pacman/pactest.py @@ -17,8 +17,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import os, sys, glob +import glob from optparse import OptionParser +import os +import shutil +import sys +import tempfile import pmenv import util @@ -63,6 +67,9 @@ def createOptParser(): parser.add_option("-t", "--test", action = "callback", callback = globTests, dest = "testcases", help = "specify test case(s)") + parser.add_option("--keep-root", action = "store_true", + dest = "keeproot", default = False, + help = "don't remove the generated pacman root filesystem") parser.add_option("--nolog", action = "store_true", dest = "nolog", default = False, help = "do not log pacman messages") @@ -80,7 +87,8 @@ def createOptParser(): if __name__ == "__main__": # instantiate env and parser objects - env = pmenv.pmenv() + root_path = tempfile.mkdtemp() + env = pmenv.pmenv(root=root_path) opt_parser = createOptParser() (opts, args) = opt_parser.parse_args() @@ -95,16 +103,23 @@ if __name__ == "__main__": if opts.testcases is None or len(opts.testcases) == 0: print "no tests defined, nothing to do" + os.rmdir(root_path) sys.exit(2) - else: - for i in opts.testcases: - env.addtest(i) - # run tests and print overall results - env.run() - env.results() + for i in opts.testcases: + env.addtest(i) + + # run tests and print overall results + env.run() + env.results() - if env.failed > 0: - sys.exit(1) + if env.failed > 0: + print "pacman testing root saved: %s" % root_path + sys.exit(1) + + if not opts.keeproot: + shutil.rmtree(root_path) + else: + print "pacman testing root saved: %s" % root_path # vim: set ts=4 sw=4 et: diff --git a/test/pacman/pmdb.py b/test/pacman/pmdb.py index b31498a7..1af24ae9 100755 --- a/test/pacman/pmdb.py +++ b/test/pacman/pmdb.py @@ -89,6 +89,12 @@ class pmdb(object): def __str__(self): return "%s" % self.treename + def getverify(self): + for value in "Always","Never","Optional": + if value in self.treename: + return value + return "Never" + def getpkg(self, name): """ """ @@ -150,6 +156,8 @@ class pmdb(object): pkg.size = int(fd.readline().strip("\n")) elif line == "%MD5SUM%": pkg.md5sum = fd.readline().strip("\n") + elif line == "%PGPSIG%": + pkg.pgpsig = fd.readline().strip("\n") elif line == "%REPLACES%": pkg.replaces = _getsection(fd) elif line == "%DEPENDS%": @@ -241,6 +249,8 @@ class pmdb(object): data.append(_mksection("CSIZE", pkg.csize)) if pkg.md5sum: data.append(_mksection("MD5SUM", pkg.md5sum)) + if pkg.pgpsig: + data.append(_mksection("PGPSIG", pkg.pgpsig)) if data: data.append("") filename = os.path.join(path, "desc") diff --git a/test/pacman/pmpkg.py b/test/pacman/pmpkg.py index be177f35..4568adb9 100755 --- a/test/pacman/pmpkg.py +++ b/test/pacman/pmpkg.py @@ -27,7 +27,7 @@ import util class pmpkg(object): """Package object. - Object holding data from an ArchLinux package. + Object holding data from an Arch Linux package. """ def __init__(self, name, version = "1.0-1"): @@ -47,6 +47,7 @@ class pmpkg(object): self.csize = 0 self.reason = 0 self.md5sum = "" # sync only + self.pgpsig = "" # sync only self.replaces = [] self.depends = [] self.optdepends = [] @@ -62,7 +63,7 @@ class pmpkg(object): "pre_remove": "", "post_remove": "", "pre_upgrade": "", - "post_upgrade": "" + "post_upgrade": "", } def __str__(self): @@ -88,7 +89,7 @@ class pmpkg(object): return "%s%s" % (self.fullname(), util.PM_EXT_PKG) def makepkg(self, path): - """Creates an ArchLinux package archive. + """Creates an Arch Linux package archive. A package archive is generated in the location 'path', based on the data from the object. @@ -133,7 +134,7 @@ class pmpkg(object): util.mkfile(".PKGINFO", "\n".join(data)) # .INSTALL - if len(self.install.values()) > 0: + if any(self.install.values()): util.mkinstallfile(".INSTALL", self.install) # safely create the dir diff --git a/test/pacman/tests/replace101.py b/test/pacman/tests/replace101.py new file mode 100644 index 00000000..86c40ac6 --- /dev/null +++ b/test/pacman/tests/replace101.py @@ -0,0 +1,25 @@ +self.description = "Sysupgrade with a versioned replacement" + +sp1 = pmpkg("python2-yaml", "5-1") +sp1.replaces = ["python-yaml<5"] +sp1.conflicts = ["python-yaml<5"] +sp1.files = ["lib/python2/file"] +self.addpkg2db("sync", sp1) + +# the python3 version +sp2 = pmpkg("python-yaml", "5-1") +sp2.files = ["lib/python3/file"] +self.addpkg2db("sync", sp2) + +lp1 = pmpkg("python-yaml", "4-1") +lp1.files = ["lib/python2/file"] +self.addpkg2db("local", lp1) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=python-yaml") +self.addrule("PKG_VERSION=python2-yaml|5-1") +self.addrule("FILE_EXIST=lib/python2/file") + +self.expectfailure = True diff --git a/test/pacman/tests/replace102.py b/test/pacman/tests/replace102.py new file mode 100644 index 00000000..c6e2e5f0 --- /dev/null +++ b/test/pacman/tests/replace102.py @@ -0,0 +1,27 @@ +self.description = "Replace a package with a file in 'backup' (local modified)" +# FS#24543 + +lp = pmpkg("dummy") +lp.files = ["etc/dummy.conf*", "bin/dummy"] +lp.backup = ["etc/dummy.conf"] +self.addpkg2db("local", lp) + +sp = pmpkg("replacement") +sp.replaces = ["dummy"] +sp.files = ["etc/dummy.conf", "bin/dummy*"] +sp.backup = ["etc/dummy.conf"] +self.addpkg2db("sync", sp) + +self.args = "-Su" + +self.addrule("!PKG_EXIST=dummy") +self.addrule("PKG_EXIST=replacement") + +self.addrule("FILE_EXIST=etc/dummy.conf") +self.addrule("!FILE_MODIFIED=etc/dummy.conf") +self.addrule("!FILE_PACNEW=etc/dummy.conf") +self.addrule("!FILE_PACSAVE=etc/dummy.conf") + +self.addrule("FILE_EXIST=bin/dummy") + +self.expectfailure = True diff --git a/test/pacman/tests/sign001.py b/test/pacman/tests/sign001.py new file mode 100644 index 00000000..0ae417b7 --- /dev/null +++ b/test/pacman/tests/sign001.py @@ -0,0 +1,9 @@ +self.description = "Add a signature to a package DB" + +sp = pmpkg("pkg1") +sp.pgpsig = "asdfasdfsdfasdfsdafasdfsdfasd" +self.addpkg2db("sync+Always", sp) + +self.args = "-Ss" + +self.addrule("PACMAN_RETCODE=0") diff --git a/test/pacman/tests/sign002.py b/test/pacman/tests/sign002.py new file mode 100644 index 00000000..b55f331e --- /dev/null +++ b/test/pacman/tests/sign002.py @@ -0,0 +1,10 @@ +self.description = "Verify a signature in a sync DB (failure)" + +sp = pmpkg("pkg1") +sp.pgpsig = "iEYEABECAAYFAkhMOggACgkQXC5GoPU6du2WVQCffVxF8GKXJIY4juJBIw/ljLrQxygAnj2QlvsUd7MdFekLX18+Ov/xzgZ1" +self.addpkg2db("sync+Always", sp) + +self.args = "-S %s" % sp.name + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=pkg1") diff --git a/test/pacman/tests/smoke002.py b/test/pacman/tests/smoke002.py index 44f2d0ec..8ff5cab7 100644 --- a/test/pacman/tests/smoke002.py +++ b/test/pacman/tests/smoke002.py @@ -10,10 +10,8 @@ self.addpkg(p2) self.args = "-U %s %s" % (p1.filename(), p2.filename()) -# Note that the current cutoff on line length is 512K, so the first package -# will succeed while the second one will fail to record the description. -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_EXIST=pkg1") -self.addrule("PKG_DESC=pkg1|%s" % p1.desc) -self.addrule("PKG_EXIST=pkg1") -self.addrule("!PKG_DESC=pkg1|%s" % p2.desc) +# We error out when fed a package with an invalid description; the second one +# fits the bill in this case as the desc is > 512K +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg1") diff --git a/test/pacman/tests/smoke004.py b/test/pacman/tests/smoke004.py new file mode 100644 index 00000000..1f9b883d --- /dev/null +++ b/test/pacman/tests/smoke004.py @@ -0,0 +1,11 @@ +self.description = "Read a package DB with several PGP signatures" + +for i in range(1000): + sp = pmpkg("pkg%03d" % i) + sp.desc = "test description for package %d" % i + sp.pgpsig = "asdfasdfsdfasdfsdafasdfsdfasd" + self.addpkg2db("sync", sp) + +self.args = "-Ss" + +self.addrule("PACMAN_RETCODE=0") diff --git a/test/pacman/util.py b/test/pacman/util.py index 47fde310..ddd955a2 100755 --- a/test/pacman/util.py +++ b/test/pacman/util.py @@ -132,8 +132,9 @@ def mkcfgfile(filename, root, option, db): if key != "local": value = db[key] data.append("[%s]\n" \ + "VerifySig = %s\n" \ "Server = file://%s" \ - % (value.treename, + % (value.treename, value.getverify(), \ os.path.join(root, SYNCREPO, value.treename))) for optkey, optval in value.option.iteritems(): data.extend(["%s = %s" % (optkey, j) for j in optval]) diff --git a/test/util/vercmptest.sh b/test/util/vercmptest.sh index 6b3869c5..7ebeba53 100755 --- a/test/util/vercmptest.sh +++ b/test/util/vercmptest.sh @@ -62,7 +62,7 @@ runtest() { # use first arg as our binary if specified [ -n "$1" ] && bin="$1" -if [ ! $(type -p "$bin") ]; then +if ! type -p "$bin"; then echo "vercmp binary ($bin) could not be located" exit 1 fi diff --git a/valgrind.supp b/valgrind.supp index 94618c08..1d6952d8 100644 --- a/valgrind.supp +++ b/valgrind.supp @@ -46,3 +46,13 @@ Memcheck:Value8 fun:BN_mod_exp_mont_consttime } +{ + openssl-supp-load-compressions + Memcheck:Leak + fun:malloc + fun:CRYPTO_malloc + ... + fun:load_builtin_compressions + fun:SSL_COMP_get_compression_methods + fun:SSL_library_init +} |