Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libalpm/.gitignore1
-rw-r--r--lib/libalpm/Makefile.am26
-rw-r--r--lib/libalpm/add.c131
-rw-r--r--lib/libalpm/add.h2
-rw-r--r--lib/libalpm/alpm.c10
-rw-r--r--lib/libalpm/alpm.h166
-rw-r--r--lib/libalpm/alpm_list.c36
-rw-r--r--lib/libalpm/alpm_list.h3
-rw-r--r--lib/libalpm/backup.c4
-rw-r--r--lib/libalpm/backup.h2
-rw-r--r--lib/libalpm/base64.c8
-rw-r--r--lib/libalpm/base64.h2
-rw-r--r--lib/libalpm/be_local.c279
-rw-r--r--lib/libalpm/be_package.c221
-rw-r--r--lib/libalpm/be_sync.c160
-rw-r--r--lib/libalpm/conflict.c128
-rw-r--r--lib/libalpm/conflict.h5
-rw-r--r--lib/libalpm/db.c40
-rw-r--r--lib/libalpm/db.h4
-rw-r--r--lib/libalpm/delta.c70
-rw-r--r--lib/libalpm/delta.h9
-rw-r--r--lib/libalpm/deps.c82
-rw-r--r--lib/libalpm/deps.h2
-rw-r--r--lib/libalpm/diskspace.c209
-rw-r--r--lib/libalpm/diskspace.h11
-rw-r--r--lib/libalpm/dload.c30
-rw-r--r--lib/libalpm/dload.h5
-rw-r--r--lib/libalpm/error.c10
-rw-r--r--lib/libalpm/filelist.c137
-rw-r--r--lib/libalpm/filelist.h35
-rw-r--r--lib/libalpm/graph.c4
-rw-r--r--lib/libalpm/graph.h4
-rw-r--r--lib/libalpm/group.c6
-rw-r--r--lib/libalpm/group.h2
-rw-r--r--lib/libalpm/handle.c50
-rw-r--r--lib/libalpm/handle.h15
-rw-r--r--lib/libalpm/libalpm.pc.in12
-rw-r--r--lib/libalpm/log.c4
-rw-r--r--lib/libalpm/log.h2
-rw-r--r--lib/libalpm/md5.c81
-rw-r--r--lib/libalpm/package.c120
-rw-r--r--lib/libalpm/package.h20
-rw-r--r--lib/libalpm/pkghash.c116
-rw-r--r--lib/libalpm/pkghash.h16
-rw-r--r--lib/libalpm/remove.c214
-rw-r--r--lib/libalpm/remove.h2
-rw-r--r--lib/libalpm/sha2.c87
-rw-r--r--lib/libalpm/signing.c51
-rw-r--r--lib/libalpm/signing.h2
-rw-r--r--lib/libalpm/sync.c239
-rw-r--r--lib/libalpm/sync.h2
-rw-r--r--lib/libalpm/trans.c13
-rw-r--r--lib/libalpm/trans.h2
-rw-r--r--lib/libalpm/util.c717
-rw-r--r--lib/libalpm/util.h48
-rw-r--r--lib/libalpm/version.c4
56 files changed, 2140 insertions, 1521 deletions
diff --git a/lib/libalpm/.gitignore b/lib/libalpm/.gitignore
index 36d41441..82318d3f 100644
--- a/lib/libalpm/.gitignore
+++ b/lib/libalpm/.gitignore
@@ -2,3 +2,4 @@
.libs
*.lo
*.la
+libalpm.pc
diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am
index 99f9c1b7..911e52bf 100644
--- a/lib/libalpm/Makefile.am
+++ b/lib/libalpm/Makefile.am
@@ -7,7 +7,10 @@ include_HEADERS = alpm_list.h alpm.h
DEFS = -DLOCALEDIR=\"@localedir@\" @DEFS@
-AM_CFLAGS = -pedantic -D_GNU_SOURCE
+AM_CPPFLAGS = \
+ -imacros $(top_builddir)/config.h
+
+AM_CFLAGS = -pedantic -D_GNU_SOURCE $(WARNING_CFLAGS)
if ENABLE_VISIBILITY_CC
if DARWIN
@@ -20,6 +23,9 @@ if ENABLE_GNU89_INLINE_CC
AM_CFLAGS += -fgnu89-inline
endif
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libalpm.pc
+
libalpm_la_SOURCES = \
add.h add.c \
alpm.h alpm.c \
@@ -35,6 +41,7 @@ libalpm_la_SOURCES = \
diskspace.h diskspace.c \
dload.h dload.c \
error.c \
+ filelist.h filelist.c \
graph.h graph.c \
group.h group.c \
handle.h handle.c \
@@ -60,7 +67,20 @@ libalpm_la_SOURCES += \
base64.h base64.c
endif
-libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO) @LIBCURL@
-libalpm_la_LIBADD = $(LTLIBINTL)
+libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO)
+
+libalpm_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(GPGME_CFLAGS) \
+ $(LIBARCHIVE_CFLAGS) \
+ $(LIBCURL_CFLAGS) \
+ $(LIBSSL_CFLAGS)
+
+libalpm_la_LIBADD = \
+ $(LTLIBINTL) \
+ $(GPGME_LIBS) \
+ $(LIBARCHIVE_LIBS) \
+ $(LIBCURL_LIBS) \
+ $(LIBSSL_LIBS)
# vim:set ts=2 sw=2 noet:
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index c49d99b4..edddc318 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -1,7 +1,7 @@
/*
* add.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,19 +18,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <errno.h>
-#include <time.h>
#include <string.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <inttypes.h> /* int64_t */
-#include <stdint.h> /* intmax_t */
+#include <stdint.h> /* int64_t */
/* libarchive */
#include <archive.h>
@@ -132,6 +128,18 @@ static int perform_extraction(alpm_handle_t *handle, struct archive *archive,
return 0;
}
+static int try_rename(alpm_handle_t *handle, const char *src, const char *dest)
+{
+ if(rename(src, dest)) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
+ src, dest, strerror(errno));
+ alpm_logaction(handle, "error: could not rename %s to %s (%s)\n",
+ src, dest, strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
struct archive_entry *entry, alpm_pkg_t *newpkg, alpm_pkg_t *oldpkg)
{
@@ -146,8 +154,6 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
entryname = archive_entry_pathname(entry);
entrymode = archive_entry_mode(entry);
- memset(filename, 0, PATH_MAX); /* just to be sure */
-
if(strcmp(entryname, ".INSTALL") == 0) {
/* the install script goes inside the db */
snprintf(filename, PATH_MAX, "%s%s-%s/install",
@@ -170,7 +176,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
}
/* if a file is in NoExtract then we never extract it */
- if(alpm_list_find_str(handle->noextract, entryname)) {
+ if(alpm_list_find(handle->noextract, entryname, _alpm_fnmatch)) {
_alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract, skipping extraction\n",
entryname);
alpm_logaction(handle, "note: %s is in NoExtract, skipping extraction\n",
@@ -250,7 +256,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
} else if(S_ISREG(entrymode)) {
/* case 4,7: */
/* if file is in NoUpgrade, don't touch it */
- if(alpm_list_find_str(handle->noupgrade, entryname)) {
+ if(alpm_list_find(handle->noupgrade, entryname, _alpm_fnmatch)) {
notouch = 1;
} else {
alpm_backup_t *backup;
@@ -282,17 +288,18 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
STRDUP(entryname_orig, entryname, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
if(needbackup) {
- char checkfile[PATH_MAX];
+ char *checkfile;
char *hash_local = NULL, *hash_pkg = NULL;
- int ret;
+ size_t len;
- snprintf(checkfile, PATH_MAX, "%s.paccheck", filename);
+ len = strlen(filename) + 10;
+ MALLOC(checkfile, len,
+ errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
+ snprintf(checkfile, len, "%s.paccheck", filename);
- ret = perform_extraction(handle, archive, entry, checkfile, entryname_orig);
- if(ret == 1) {
- /* error */
- FREE(entryname_orig);
- return 1;
+ if(perform_extraction(handle, archive, entry, checkfile, entryname_orig)) {
+ errors++;
+ goto needbackup_cleanup;
}
hash_local = alpm_compute_md5sum(filename);
@@ -320,29 +327,26 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
if(hash_local && hash_pkg && strcmp(hash_local, hash_pkg) != 0) {
/* looks like we have a local file that has a different hash as the
* file in the package, move it to a .pacorig */
- char newpath[PATH_MAX];
- snprintf(newpath, PATH_MAX, "%s.pacorig", filename);
+ char *newpath;
+ size_t newlen = strlen(filename) + 9;
+ MALLOC(newpath, newlen,
+ errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
+ snprintf(newpath, newlen, "%s.pacorig", filename);
/* move the existing file to the "pacorig" */
- if(rename(filename, newpath)) {
- _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
- filename, newpath, strerror(errno));
- alpm_logaction(handle, "error: could not rename %s to %s (%s)\n",
- filename, newpath, strerror(errno));
+ if(try_rename(handle, filename, newpath)) {
+ errors++;
errors++;
} else {
/* rename the file we extracted to the real name */
- if(rename(checkfile, filename)) {
- _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
- checkfile, filename, strerror(errno));
- alpm_logaction(handle, "error: could not rename %s to %s (%s)\n",
- checkfile, filename, strerror(errno));
+ if(try_rename(handle, checkfile, filename)) {
errors++;
} else {
_alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), filename, newpath);
alpm_logaction(handle, "warning: %s saved as %s\n", filename, newpath);
}
}
+ free(newpath);
} else {
/* local file is identical to pkg one, so just remove pkg one */
unlink(checkfile);
@@ -356,11 +360,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
_alpm_log(handle, ALPM_LOG_DEBUG, "action: installing new file: %s\n",
entryname_orig);
- if(rename(checkfile, filename)) {
- _alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
- checkfile, filename, strerror(errno));
- alpm_logaction(handle, "error: could not rename %s to %s (%s)\n",
- checkfile, filename, strerror(errno));
+ if(try_rename(handle, checkfile, filename)) {
errors++;
}
} else {
@@ -382,29 +382,30 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
_alpm_log(handle, ALPM_LOG_DEBUG, "action: leaving existing file in place\n");
unlink(checkfile);
} else {
- char newpath[PATH_MAX];
+ char *newpath;
+ size_t newlen = strlen(filename) + 8;
_alpm_log(handle, ALPM_LOG_DEBUG, "action: keeping current file and installing"
" new one with .pacnew ending\n");
- snprintf(newpath, PATH_MAX, "%s.pacnew", filename);
- if(rename(checkfile, newpath)) {
- _alpm_log(handle, ALPM_LOG_ERROR, _("could not install %s as %s (%s)\n"),
- filename, newpath, strerror(errno));
- alpm_logaction(handle, "error: could not install %s as %s (%s)\n",
- filename, newpath, strerror(errno));
+ MALLOC(newpath, newlen,
+ errors++; handle->pm_errno = ALPM_ERR_MEMORY; goto needbackup_cleanup);
+ snprintf(newpath, newlen, "%s.pacnew", filename);
+ if(try_rename(handle, checkfile, newpath)) {
+ errors++;
} else {
_alpm_log(handle, ALPM_LOG_WARNING, _("%s installed as %s\n"),
filename, newpath);
alpm_logaction(handle, "warning: %s installed as %s\n",
filename, newpath);
}
+ free(newpath);
}
}
- FREE(hash_local);
- FREE(hash_pkg);
+needbackup_cleanup:
+ free(checkfile);
+ free(hash_local);
+ free(hash_pkg);
} else {
- int ret;
-
/* we didn't need a backup */
if(notouch) {
/* change the path to a .pacnew extension */
@@ -423,11 +424,11 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
unlink(filename);
}
- ret = perform_extraction(handle, archive, entry, filename, entryname_orig);
- if(ret == 1) {
+ if(perform_extraction(handle, archive, entry, filename, entryname_orig)) {
/* error */
- FREE(entryname_orig);
- return 1;
+ free(entryname_orig);
+ errors++;
+ return errors;
}
/* calculate an hash if this is in newpkg's backup */
@@ -444,7 +445,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
backup->hash = newhash;
}
}
- FREE(entryname_orig);
+ free(entryname_orig);
return errors;
}
@@ -522,31 +523,20 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) {
struct archive *archive;
struct archive_entry *entry;
- int cwdfd;
+ struct stat buf;
+ int fd, cwdfd;
_alpm_log(handle, ALPM_LOG_DEBUG, "extracting files\n");
- if((archive = archive_read_new()) == NULL) {
- handle->pm_errno = ALPM_ERR_LIBARCHIVE;
- ret = -1;
- goto cleanup;
- }
-
- archive_read_support_compression_all(archive);
- archive_read_support_format_all(archive);
-
- _alpm_log(handle, ALPM_LOG_DEBUG, "archive: %s\n", pkgfile);
- if(archive_read_open_filename(archive, pkgfile,
- ALPM_BUFFER_SIZE) != ARCHIVE_OK) {
- handle->pm_errno = ALPM_ERR_PKG_OPEN;
+ fd = _alpm_open_archive(db->handle, pkgfile, &buf,
+ &archive, ALPM_ERR_PKG_OPEN);
+ if(fd < 0) {
ret = -1;
goto cleanup;
}
/* save the cwd so we can restore it later */
- do {
- cwdfd = open(".", O_RDONLY);
- } while(cwdfd == -1 && errno == EINTR);
+ OPEN(cwdfd, ".", O_RDONLY);
if(cwdfd < 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
}
@@ -555,6 +545,8 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
if(chdir(handle->root) != 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"),
handle->root, strerror(errno));
+ archive_read_finish(archive);
+ CLOSE(fd);
ret = -1;
goto cleanup;
}
@@ -596,6 +588,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
errors += extract_single_file(handle, archive, entry, newpkg, oldpkg);
}
archive_read_finish(archive);
+ CLOSE(fd);
/* restore the old cwd if we have it */
if(cwdfd >= 0) {
@@ -603,7 +596,7 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
_alpm_log(handle, ALPM_LOG_ERROR,
_("could not restore working directory (%s)\n"), strerror(errno));
}
- close(cwdfd);
+ CLOSE(cwdfd);
}
if(errors) {
diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h
index 77a3d22a..d1368e8a 100644
--- a/lib/libalpm/add.h
+++ b/lib/libalpm/add.h
@@ -1,7 +1,7 @@
/*
* add.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c
index 38843342..c58a4069 100644
--- a/lib/libalpm/alpm.c
+++ b/lib/libalpm/alpm.c
@@ -1,7 +1,7 @@
/*
* alpm.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
@@ -21,8 +21,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#ifdef HAVE_LIBCURL
#include <curl/curl.h>
#endif
@@ -47,9 +45,9 @@
* @return a context handle on success, NULL on error, err will be set if provided
*/
alpm_handle_t SYMEXPORT *alpm_initialize(const char *root, const char *dbpath,
- enum _alpm_errno_t *err)
+ alpm_errno_t *err)
{
- enum _alpm_errno_t myerr;
+ alpm_errno_t myerr;
const char *lf = "db.lck";
size_t lockfilelen;
alpm_handle_t *myhandle = _alpm_handle_new();
@@ -108,7 +106,7 @@ int SYMEXPORT alpm_release(alpm_handle_t *myhandle)
myhandle->db_local = NULL;
}
- if(alpm_db_unregister_all(myhandle) == -1) {
+ if(alpm_unregister_all_syncdbs(myhandle) == -1) {
ret = -1;
}
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 6df3e1f5..1d6a8c6c 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -1,7 +1,7 @@
/*
* alpm.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
@@ -27,14 +27,12 @@
extern "C" {
#endif
-#include <sys/types.h> /* for off_t */
-#include <time.h> /* for time_t */
-#include <stdarg.h> /* for va_list */
+#include <stdint.h> /* int64_t */
+#include <sys/types.h> /* off_t */
+#include <stdarg.h> /* va_list */
#include <alpm_list.h>
-#define DEPRECATED __attribute__((deprecated))
-
/*
* Arch Linux Package Management library
*/
@@ -44,15 +42,14 @@ extern "C" {
* @{
*/
+typedef int64_t alpm_time_t;
+
/*
* Enumerations
* These ones are used in multiple contexts, so are forward-declared.
*/
-/**
- * Install reasons.
- * Why the package was installed.
- */
+/** Package install reasons. */
typedef enum _alpm_pkgreason_t {
/** Explicitly requested by the user. */
ALPM_PKG_REASON_EXPLICIT = 0,
@@ -60,12 +57,22 @@ typedef enum _alpm_pkgreason_t {
ALPM_PKG_REASON_DEPEND = 1
} alpm_pkgreason_t;
+/** Location a package object was loaded from. */
typedef enum _alpm_pkgfrom_t {
- PKG_FROM_FILE = 1,
- PKG_FROM_LOCALDB,
- PKG_FROM_SYNCDB
+ ALPM_PKG_FROM_FILE = 1,
+ ALPM_PKG_FROM_LOCALDB,
+ ALPM_PKG_FROM_SYNCDB
} alpm_pkgfrom_t;
+/** Location a package object was loaded from. */
+typedef enum _alpm_pkgvalidation_t {
+ ALPM_PKG_VALIDATION_UNKNOWN = 0,
+ ALPM_PKG_VALIDATION_NONE = (1 << 0),
+ ALPM_PKG_VALIDATION_MD5SUM = (1 << 1),
+ ALPM_PKG_VALIDATION_SHA256SUM = (1 << 2),
+ ALPM_PKG_VALIDATION_SIGNATURE = (1 << 3)
+} alpm_pkgvalidation_t;
+
/** Types of version constraints in dependency specs. */
typedef enum _alpm_depmod_t {
/** No version constraint */
@@ -92,9 +99,7 @@ typedef enum _alpm_fileconflicttype_t {
ALPM_FILECONFLICT_FILESYSTEM
} alpm_fileconflicttype_t;
-/**
- * PGP signature verification options
- */
+/** PGP signature verification options */
typedef enum _alpm_siglevel_t {
ALPM_SIG_PACKAGE = (1 << 0),
ALPM_SIG_PACKAGE_OPTIONAL = (1 << 1),
@@ -109,9 +114,7 @@ typedef enum _alpm_siglevel_t {
ALPM_SIG_USE_DEFAULT = (1 << 31)
} alpm_siglevel_t;
-/**
- * PGP signature verification status return codes
- */
+/** PGP signature verification status return codes */
typedef enum _alpm_sigstatus_t {
ALPM_SIGSTATUS_VALID,
ALPM_SIGSTATUS_KEY_EXPIRED,
@@ -121,9 +124,7 @@ typedef enum _alpm_sigstatus_t {
ALPM_SIGSTATUS_INVALID
} alpm_sigstatus_t;
-/**
- * PGP signature verification status return codes
- */
+/** PGP signature verification status return codes */
typedef enum _alpm_sigvalidity_t {
ALPM_SIGVALIDITY_FULL,
ALPM_SIGVALIDITY_MARGINAL,
@@ -144,6 +145,7 @@ typedef struct __alpm_trans_t alpm_trans_t;
typedef struct _alpm_depend_t {
char *name;
char *version;
+ char *desc;
unsigned long name_hash;
alpm_depmod_t mod;
} alpm_depend_t;
@@ -152,7 +154,7 @@ typedef struct _alpm_depend_t {
typedef struct _alpm_depmissing_t {
char *target;
alpm_depend_t *depend;
- /* this is used in case of remove dependency error only */
+ /* this is used only in the case of a remove dependency error */
char *causingpkg;
} alpm_depmissing_t;
@@ -222,11 +224,15 @@ typedef struct _alpm_pgpkey_t {
char *uid;
char *name;
char *email;
- time_t created;
- time_t expires;
+ alpm_time_t created;
+ alpm_time_t expires;
+ unsigned int length;
+ unsigned int revoked;
+ char pubkey_algo;
} alpm_pgpkey_t;
-/** Signature result. Contains the key, status, and validity of a given
+/**
+ * Signature result. Contains the key, status, and validity of a given
* signature.
*/
typedef struct _alpm_sigresult_t {
@@ -235,7 +241,8 @@ typedef struct _alpm_sigresult_t {
alpm_sigvalidity_t validity;
} alpm_sigresult_t;
-/** Signature list. Contains the number of signatures found and a pointer to an
+/**
+ * Signature list. Contains the number of signatures found and a pointer to an
* array of results. The array is of size count.
*/
typedef struct _alpm_siglist_t {
@@ -247,9 +254,7 @@ typedef struct _alpm_siglist_t {
* Logging facilities
*/
-/**
- * Logging Levels
- */
+/** Logging Levels */
typedef enum _alpm_loglevel_t {
ALPM_LOG_ERROR = 1,
ALPM_LOG_WARNING = (1 << 1),
@@ -260,7 +265,8 @@ typedef enum _alpm_loglevel_t {
typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list);
int alpm_logaction(alpm_handle_t *handle, const char *fmt, ...);
-/** Events.
+/**
+ * Events.
* NULL parameters are passed to in all events unless specified otherwise.
*/
typedef enum _alpm_event_t {
@@ -341,13 +347,18 @@ typedef enum _alpm_event_t {
/** Disk space usage will be computed for a package */
ALPM_EVENT_DISKSPACE_START,
/** Disk space usage was computed for a package */
- ALPM_EVENT_DISKSPACE_DONE,
+ ALPM_EVENT_DISKSPACE_DONE
} alpm_event_t;
/** Event callback */
typedef void (*alpm_cb_event)(alpm_event_t, void *, void *);
-/** Questions */
+/**
+ * Questions.
+ * Unlike the events or progress enumerations, this enum has bitmask values
+ * so a frontend can use a bitmask map to supply preselected answers to the
+ * different types of questions.
+ */
typedef enum _alpm_question_t {
ALPM_QUESTION_INSTALL_IGNOREPKG = 1,
ALPM_QUESTION_REPLACE_PKG = (1 << 1),
@@ -370,7 +381,7 @@ typedef enum _alpm_progress_t {
ALPM_PROGRESS_CONFLICTS_START,
ALPM_PROGRESS_DISKSPACE_START,
ALPM_PROGRESS_INTEGRITY_START,
- ALPM_PROGRESS_LOAD_START,
+ ALPM_PROGRESS_LOAD_START
} alpm_progress_t;
/** Progress callback */
@@ -530,8 +541,8 @@ const char *alpm_option_get_arch(alpm_handle_t *handle);
/** Sets the targeted architecture. */
int alpm_option_set_arch(alpm_handle_t *handle, const char *arch);
-int alpm_option_get_usedelta(alpm_handle_t *handle);
-int alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta);
+double alpm_option_get_deltaratio(alpm_handle_t *handle);
+int alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio);
int alpm_option_get_checkspace(alpm_handle_t *handle);
int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace);
@@ -552,7 +563,7 @@ int alpm_option_set_default_siglevel(alpm_handle_t *handle, alpm_siglevel_t leve
* libalpm functions.
* @return a reference to the local database
*/
-alpm_db_t *alpm_option_get_localdb(alpm_handle_t *handle);
+alpm_db_t *alpm_get_localdb(alpm_handle_t *handle);
/** Get the list of sync databases.
* Returns a list of alpm_db_t structures, one for each registered
@@ -560,7 +571,7 @@ alpm_db_t *alpm_option_get_localdb(alpm_handle_t *handle);
* @param handle the context handle
* @return a reference to an internal list of alpm_db_t structures
*/
-alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle);
+alpm_list_t *alpm_get_syncdbs(alpm_handle_t *handle);
/** Register a sync database of packages.
* @param handle the context handle
@@ -569,20 +580,20 @@ alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle);
* database; note that this must be a '.sig' file type verification
* @return an alpm_db_t* on success (the value), NULL on error
*/
-alpm_db_t *alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
+alpm_db_t *alpm_register_syncdb(alpm_handle_t *handle, const char *treename,
alpm_siglevel_t level);
-/** Unregister a package database.
- * @param db pointer to the package database to unregister
+/** Unregister all package databases.
+ * @param handle the context handle
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int alpm_db_unregister(alpm_db_t *db);
+int alpm_unregister_all_syncdbs(alpm_handle_t *handle);
-/** Unregister all package databases.
- * @param handle the context handle
+/** Unregister a package database.
+ * @param db pointer to the package database to unregister
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int alpm_db_unregister_all(alpm_handle_t *handle);
+int alpm_db_unregister(alpm_db_t *db);
/** Get the name of a package database.
* @param db pointer to the package database
@@ -615,7 +626,7 @@ int alpm_db_add_server(alpm_db_t *db, const char *url);
int alpm_db_remove_server(alpm_db_t *db, const char *url);
/** @} */
-int alpm_db_update(int level, alpm_db_t *db);
+int alpm_db_update(int force, alpm_db_t *db);
/** Get a package entry from a package database.
* @param db pointer to the package database to get the package from
@@ -635,7 +646,7 @@ alpm_list_t *alpm_db_get_pkgcache(alpm_db_t *db);
* @param name of the group
* @return the groups entry on success, NULL on error
*/
-alpm_group_t *alpm_db_readgroup(alpm_db_t *db, const char *name);
+alpm_group_t *alpm_db_get_group(alpm_db_t *db, const char *name);
/** Get the group cache of a package database.
* @param db pointer to the package database to get the group from
@@ -648,16 +659,7 @@ alpm_list_t *alpm_db_get_groupcache(alpm_db_t *db);
* @param needles a list of regular expressions to search for
* @return the list of packages matching all regular expressions on success, NULL on error
*/
-alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles);
-
-/** Set install reason for a package in db.
- * @param handle the context handle
- * @param pkg the package to update
- * @param reason the new install reason
- * @return 0 on success, -1 on error (pm_errno is set accordingly)
- */
-int alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg,
- alpm_pkgreason_t reason);
+alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t *needles);
/** @} */
@@ -754,13 +756,13 @@ const char *alpm_pkg_get_url(alpm_pkg_t *pkg);
* @param pkg a pointer to package
* @return the timestamp of the build time
*/
-time_t alpm_pkg_get_builddate(alpm_pkg_t *pkg);
+alpm_time_t alpm_pkg_get_builddate(alpm_pkg_t *pkg);
/** Returns the install timestamp of the package.
* @param pkg a pointer to package
* @return the timestamp of the install time
*/
-time_t alpm_pkg_get_installdate(alpm_pkg_t *pkg);
+alpm_time_t alpm_pkg_get_installdate(alpm_pkg_t *pkg);
/** Returns the packager's name.
* @param pkg a pointer to package
@@ -827,7 +829,7 @@ alpm_list_t *alpm_pkg_get_depends(alpm_pkg_t *pkg);
/** Returns the list of package optional dependencies.
* @param pkg a pointer to package
- * @return a reference to an internal list of strings.
+ * @return a reference to an internal list of alpm_depend_t structures.
*/
alpm_list_t *alpm_pkg_get_optdepends(alpm_pkg_t *pkg);
@@ -869,7 +871,7 @@ alpm_filelist_t *alpm_pkg_get_files(alpm_pkg_t *pkg);
* "<filename>\t<md5sum>", where the given md5sum is that of
* the file as provided by the package.
* @param pkg a pointer to package
- * @return a reference to an internal list of strings.
+ * @return a reference to a list of alpm_backup_t objects
*/
alpm_list_t *alpm_pkg_get_backup(alpm_pkg_t *pkg);
@@ -887,6 +889,12 @@ alpm_db_t *alpm_pkg_get_db(alpm_pkg_t *pkg);
*/
const char *alpm_pkg_get_base64_sig(alpm_pkg_t *pkg);
+/** Returns the method used to validate a package during install.
+ * @param pkg a pointer to package
+ * @return an enum member giving the validation method
+ */
+alpm_pkgvalidation_t alpm_pkg_get_validation(alpm_pkg_t *pkg);
+
/* End of alpm_pkg_t accessors */
/* @} */
@@ -928,10 +936,34 @@ off_t alpm_pkg_download_size(alpm_pkg_t *newpkg);
alpm_list_t *alpm_pkg_unused_deltas(alpm_pkg_t *pkg);
+/** Set install reason for a package in the local database.
+ * The provided package object must be from the local database or this method
+ * will fail. The write to the local database is performed immediately.
+ * @param pkg the package to update
+ * @param reason the new install reason
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason);
+
+
/* End of alpm_pkg */
/** @} */
/*
+ * Filelists
+ */
+
+/** Determines whether a package filelist contains a given path.
+ * The provided path should be relative to the install root with no leading
+ * slashes, e.g. "etc/localtime". When searching for directories, the path must
+ * have a trailing slash.
+ * @param filelist a pointer to a package filelist
+ * @param path the path to search for in the package
+ * @return a pointer to the matching file or NULL if not found
+ */
+alpm_file_t *alpm_filelist_contains(alpm_filelist_t *filelist, const char *path);
+
+/*
* Signatures
*/
@@ -1107,13 +1139,13 @@ char *alpm_dep_compute_string(const alpm_depend_t *dep);
*/
/* checksums */
-char *alpm_compute_md5sum(const char *name);
+char *alpm_compute_md5sum(const char *filename);
char *alpm_compute_sha256sum(const char *filename);
/** @addtogroup alpm_api_errors Error Codes
* @{
*/
-enum _alpm_errno_t {
+typedef enum _alpm_errno_t {
ALPM_ERR_MEMORY = 1,
ALPM_ERR_SYSTEM,
ALPM_ERR_BADPERMS,
@@ -1177,19 +1209,19 @@ enum _alpm_errno_t {
ALPM_ERR_LIBCURL,
ALPM_ERR_EXTERNAL_DOWNLOAD,
ALPM_ERR_GPGME
-};
+} alpm_errno_t;
/** Returns the current error code from the handle. */
-enum _alpm_errno_t alpm_errno(alpm_handle_t *handle);
+alpm_errno_t alpm_errno(alpm_handle_t *handle);
/** Returns the string corresponding to an error number. */
-const char *alpm_strerror(enum _alpm_errno_t err);
+const char *alpm_strerror(alpm_errno_t err);
/* End of alpm_api_errors */
/** @} */
alpm_handle_t *alpm_initialize(const char *root, const char *dbpath,
- enum _alpm_errno_t *err);
+ alpm_errno_t *err);
int alpm_release(alpm_handle_t *handle);
enum alpm_caps {
diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c
index 3aa4f9bc..39eded13 100644
--- a/lib/libalpm/alpm_list.c
+++ b/lib/libalpm/alpm_list.c
@@ -1,7 +1,7 @@
/*
* alpm_list.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -204,7 +204,8 @@ alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second)
*
* @return the resultant list
*/
-alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, alpm_list_fn_cmp fn)
+alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right,
+ alpm_list_fn_cmp fn)
{
alpm_list_t *newlist, *lp, *tail_ptr, *left_tail_ptr, *right_tail_ptr;
@@ -273,20 +274,26 @@ alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right, a
*
* @return the resultant list
*/
-alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n, alpm_list_fn_cmp fn)
+alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n,
+ alpm_list_fn_cmp fn)
{
if(n > 1) {
- alpm_list_t *left = list;
- alpm_list_t *lastleft = alpm_list_nth(list, n/2 - 1);
- alpm_list_t *right = lastleft->next;
+ size_t half = n / 2;
+ size_t i = half - 1;
+ alpm_list_t *left = list, *lastleft = list, *right;
+
+ while(i--) {
+ lastleft = lastleft->next;
+ }
+ right = lastleft->next;
/* tidy new lists */
lastleft->next = NULL;
right->prev = left->prev;
left->prev = lastleft;
- left = alpm_list_msort(left, n/2, fn);
- right = alpm_list_msort(right, n - (n/2), fn);
+ left = alpm_list_msort(left, half, fn);
+ right = alpm_list_msort(right, n - half, fn);
list = alpm_list_mmerge(left, right, fn);
}
return list;
@@ -579,19 +586,6 @@ alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list)
}
}
-/**
- * @brief Get the data member of a list node.
- *
- * @param node the list node
- *
- * @return the contained data, or NULL if none
- */
-void SYMEXPORT *alpm_list_getdata(const alpm_list_t *node)
-{
- if(node == NULL) return NULL;
- return node->data;
-}
-
/* Misc */
/**
diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h
index cd7b0291..8f743a28 100644
--- a/lib/libalpm/alpm_list.h
+++ b/lib/libalpm/alpm_list.h
@@ -1,7 +1,7 @@
/*
* alpm_list.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -71,7 +71,6 @@ alpm_list_t *alpm_list_nth(const alpm_list_t *list, size_t n);
alpm_list_t *alpm_list_next(const alpm_list_t *list);
alpm_list_t *alpm_list_previous(const alpm_list_t *list);
alpm_list_t *alpm_list_last(const alpm_list_t *list);
-void *alpm_list_getdata(const alpm_list_t *entry);
/* misc */
size_t alpm_list_count(const alpm_list_t *list);
diff --git a/lib/libalpm/backup.c b/lib/libalpm/backup.c
index 728c1d05..98b5f5e3 100644
--- a/lib/libalpm/backup.c
+++ b/lib/libalpm/backup.c
@@ -1,7 +1,7 @@
/*
* backup.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2005 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
@@ -21,8 +21,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <string.h>
diff --git a/lib/libalpm/backup.h b/lib/libalpm/backup.h
index 0b84a68c..c539406d 100644
--- a/lib/libalpm/backup.h
+++ b/lib/libalpm/backup.h
@@ -1,7 +1,7 @@
/*
* backup.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/lib/libalpm/base64.c b/lib/libalpm/base64.c
index 5c9fa814..32c44459 100644
--- a/lib/libalpm/base64.c
+++ b/lib/libalpm/base64.c
@@ -32,6 +32,8 @@
* * removal of SELF_TEST code
*/
+#include <stdint.h>
+
#include "base64.h"
static const unsigned char base64_enc_map[64] =
@@ -62,6 +64,7 @@ static const unsigned char base64_dec_map[128] =
49, 50, 51, 127, 127, 127, 127, 127
};
+#if 0
/*
* Encode a buffer into base64 format
*/
@@ -124,6 +127,7 @@ int base64_encode( unsigned char *dst, size_t *dlen,
return( 0 );
}
+#endif
/*
* Decode a base64-formatted buffer
@@ -131,8 +135,8 @@ int base64_encode( unsigned char *dst, size_t *dlen,
int base64_decode( unsigned char *dst, size_t *dlen,
const unsigned char *src, size_t slen )
{
- size_t i, j, n;
- unsigned long x;
+ size_t i, n;
+ uint32_t j, x;
unsigned char *p;
for( i = j = n = 0; i < slen; i++ )
diff --git a/lib/libalpm/base64.h b/lib/libalpm/base64.h
index 406aefa1..df684ab7 100644
--- a/lib/libalpm/base64.h
+++ b/lib/libalpm/base64.h
@@ -30,6 +30,7 @@
#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x0010 /**< Output buffer too small. */
#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x0012 /**< Invalid character in input. */
+#if 0
/**
* \brief Encode a buffer into base64 format
*
@@ -47,6 +48,7 @@
*/
int base64_encode( unsigned char *dst, size_t *dlen,
const unsigned char *src, size_t slen );
+#endif
/**
* \brief Decode a base64-formatted buffer
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index 56cf38bb..bbc0a8ac 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -1,7 +1,7 @@
/*
* be_local.c : backend for the local database
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,8 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -28,7 +26,6 @@
#include <stdint.h> /* intmax_t */
#include <sys/stat.h>
#include <dirent.h>
-#include <time.h>
#include <limits.h> /* PATH_MAX */
/* libalpm */
@@ -40,6 +37,7 @@
#include "handle.h"
#include "package.h"
#include "deps.h"
+#include "filelist.h"
static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq);
@@ -69,13 +67,13 @@ static const char *_cache_get_url(alpm_pkg_t *pkg)
return pkg->url;
}
-static time_t _cache_get_builddate(alpm_pkg_t *pkg)
+static alpm_time_t _cache_get_builddate(alpm_pkg_t *pkg)
{
LAZY_LOAD(INFRQ_DESC, 0);
return pkg->builddate;
}
-static time_t _cache_get_installdate(alpm_pkg_t *pkg)
+static alpm_time_t _cache_get_installdate(alpm_pkg_t *pkg)
{
LAZY_LOAD(INFRQ_DESC, 0);
return pkg->installdate;
@@ -105,6 +103,12 @@ static alpm_pkgreason_t _cache_get_reason(alpm_pkg_t *pkg)
return pkg->reason;
}
+static alpm_pkgvalidation_t _cache_get_validation(alpm_pkg_t *pkg)
+{
+ LAZY_LOAD(INFRQ_DESC, -1);
+ return pkg->validation;
+}
+
static alpm_list_t *_cache_get_licenses(alpm_pkg_t *pkg)
{
LAZY_LOAD(INFRQ_DESC, NULL);
@@ -226,6 +230,7 @@ static struct pkg_operations local_pkg_ops = {
.get_arch = _cache_get_arch,
.get_isize = _cache_get_isize,
.get_reason = _cache_get_reason,
+ .get_validation = _cache_get_validation,
.has_scriptlet = _cache_has_scriptlet,
.get_licenses = _cache_get_licenses,
.get_groups = _cache_get_groups,
@@ -401,12 +406,11 @@ static int local_db_populate(alpm_db_t *db)
rewinddir(dbdir);
}
if(est_count >= 2) {
- /* subtract the two extra pointers to get # of children */
+ /* subtract the '.' and '..' pointers to get # of children */
est_count -= 2;
}
- /* initialize hash at 50% full */
- db->pkgcache = _alpm_pkghash_create(est_count * 2);
+ db->pkgcache = _alpm_pkghash_create(est_count);
if(db->pkgcache == NULL){
closedir(dbdir);
RET_ERR(db->handle, ALPM_ERR_MEMORY, -1);
@@ -445,7 +449,7 @@ static int local_db_populate(alpm_db_t *db)
continue;
}
- pkg->origin = PKG_FROM_LOCALDB;
+ pkg->origin = ALPM_PKG_FROM_LOCALDB;
pkg->origin_data.db = db;
pkg->ops = &local_pkg_ops;
pkg->handle = db->handle;
@@ -475,7 +479,8 @@ static int local_db_populate(alpm_db_t *db)
}
/* Note: the return value must be freed by the caller */
-char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filename)
+char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info,
+ const char *filename)
{
size_t len;
char *pkgpath;
@@ -492,7 +497,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filena
#define READ_NEXT() do { \
if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) goto error; \
- _alpm_strip_newline(line); \
+ _alpm_strip_newline(line, 0); \
} while(0)
#define READ_AND_STORE(f) do { \
@@ -505,7 +510,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filena
if(fgets(line, sizeof(line), fp) == NULL) {\
if(!feof(fp)) goto error; else break; \
} \
- if(_alpm_strip_newline(line) == 0) break; \
+ if(_alpm_strip_newline(line, 0) == 0) break; \
STRDUP(linedup, line, goto error); \
f = alpm_list_add(f, linedup); \
} while(1) /* note the while(1) and not (0) */
@@ -514,7 +519,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, const char *filena
if(fgets(line, sizeof(line), fp) == NULL) {\
if(!feof(fp)) goto error; else break; \
} \
- if(_alpm_strip_newline(line) == 0) break; \
+ if(_alpm_strip_newline(line, 0) == 0) break; \
f = alpm_list_add(f, _alpm_splitdep(line)); \
} while(1) /* note the while(1) and not (0) */
@@ -522,7 +527,6 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
{
FILE *fp = NULL;
char line[1024];
- char *pkgpath;
alpm_db_t *db = info->origin_data.db;
/* bitmask logic here:
@@ -541,18 +545,10 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
return -1;
}
- _alpm_log(db->handle, ALPM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n",
+ _alpm_log(db->handle, ALPM_LOG_FUNCTION,
+ "loading package data for %s : level=0x%x\n",
info->name, inforeq);
- pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
- if(!pkgpath || access(pkgpath, F_OK)) {
- /* directory doesn't exist or can't be opened */
- _alpm_log(db->handle, ALPM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n",
- info->name, info->version, db->treename);
- goto error;
- }
- free(pkgpath);
-
/* clear out 'line', to be certain - and to make valgrind happy */
memset(line, 0, sizeof(line));
@@ -569,7 +565,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) {
goto error;
}
- if(_alpm_strip_newline(line) == 0) {
+ if(_alpm_strip_newline(line, 0) == 0) {
/* length of stripped line was zero */
continue;
}
@@ -606,6 +602,26 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
} else if(strcmp(line, "%REASON%") == 0) {
READ_NEXT();
info->reason = (alpm_pkgreason_t)atoi(line);
+ } else if(strcmp(line, "%VALIDATION%") == 0) {
+ alpm_list_t *i, *v = NULL;
+ READ_AND_STORE_ALL(v);
+ for(i = v; i; i = alpm_list_next(i))
+ {
+ if(strcmp(i->data, "none") == 0) {
+ info->validation |= ALPM_PKG_VALIDATION_NONE;
+ } else if(strcmp(i->data, "md5") == 0) {
+ info->validation |= ALPM_PKG_VALIDATION_MD5SUM;
+ } else if(strcmp(i->data, "sha256") == 0) {
+ info->validation |= ALPM_PKG_VALIDATION_SHA256SUM;
+ } else if(strcmp(i->data, "pgp") == 0) {
+ info->validation |= ALPM_PKG_VALIDATION_SIGNATURE;
+ } else {
+ _alpm_log(db->handle, ALPM_LOG_WARNING,
+ _("unknown validation type for package %s: %s\n"),
+ info->name, (const char *)i->data);
+ }
+ }
+ FREELIST(v);
} else if(strcmp(line, "%SIZE%") == 0) {
READ_NEXT();
info->isize = _alpm_strtoofft(line);
@@ -614,7 +630,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
} else if(strcmp(line, "%DEPENDS%") == 0) {
READ_AND_SPLITDEP(info->depends);
} else if(strcmp(line, "%OPTDEPENDS%") == 0) {
- READ_AND_STORE_ALL(info->optdepends);
+ READ_AND_SPLITDEP(info->optdepends);
} else if(strcmp(line, "%CONFLICTS%") == 0) {
READ_AND_SPLITDEP(info->conflicts);
} else if(strcmp(line, "%PROVIDES%") == 0) {
@@ -636,12 +652,13 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
}
free(path);
while(fgets(line, sizeof(line), fp)) {
- _alpm_strip_newline(line);
+ _alpm_strip_newline(line, 0);
if(strcmp(line, "%FILES%") == 0) {
- size_t files_count = 0, files_size = 0;
+ size_t files_count = 0, files_size = 0, len;
alpm_file_t *files = NULL;
- while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) {
+ while(fgets(line, sizeof(line), fp) &&
+ (len = _alpm_strip_newline(line, 0))) {
if(files_count >= files_size) {
size_t old_size = files_size;
if(files_size == 0) {
@@ -651,7 +668,7 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
}
files = realloc(files, sizeof(alpm_file_t) * files_size);
if(!files) {
- ALLOC_FAIL(sizeof(alpm_file_t) * files_size);
+ _alpm_alloc_fail(sizeof(alpm_file_t) * files_size);
goto error;
}
/* ensure all new memory is zeroed out, in both the initial
@@ -659,16 +676,25 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
memset(files + old_size, 0,
sizeof(alpm_file_t) * (files_size - old_size));
}
- STRDUP(files[files_count].name, line, goto error);
- /* TODO: lstat file, get mode/size */
+ /* since we know the length of the file string already,
+ * we can do malloc + memcpy rather than strdup */
+ len += 1;
+ files[files_count].name = malloc(len);
+ if(files[files_count].name == NULL) {
+ _alpm_alloc_fail(len);
+ goto error;
+ }
+ memcpy(files[files_count].name, line, len);
files_count++;
}
/* attempt to hand back any memory we don't need */
files = realloc(files, sizeof(alpm_file_t) * files_count);
+ /* make sure the list is sorted */
+ qsort(files, files_count, sizeof(alpm_file_t), _alpm_files_cmp);
info->files.count = files_count;
info->files.files = files;
} else if(strcmp(line, "%BACKUP%") == 0) {
- while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line)) {
+ while(fgets(line, sizeof(line), fp) && _alpm_strip_newline(line, 0)) {
alpm_backup_t *backup;
CALLOC(backup, 1, sizeof(alpm_backup_t), goto error);
if(_alpm_split_backup(line, &backup)) {
@@ -727,6 +753,23 @@ int _alpm_local_db_prepare(alpm_db_t *db, alpm_pkg_t *info)
return retval;
}
+static void write_deps(FILE *fp, const char *header, alpm_list_t *deplist)
+{
+ alpm_list_t *lp;
+ if(!deplist) {
+ return;
+ }
+ fputs(header, fp);
+ fputc('\n', fp);
+ for(lp = deplist; lp; lp = lp->next) {
+ char *depstring = alpm_dep_compute_string(lp->data);
+ fputs(depstring, fp);
+ fputc('\n', fp);
+ free(depstring);
+ }
+ fputc('\n', fp);
+}
+
int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq)
{
FILE *fp = NULL;
@@ -744,7 +787,8 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq
/* DESC */
if(inforeq & INFRQ_DESC) {
char *path;
- _alpm_log(db->handle, ALPM_LOG_DEBUG, "writing %s-%s DESC information back to db\n",
+ _alpm_log(db->handle, ALPM_LOG_DEBUG,
+ "writing %s-%s DESC information back to db\n",
info->name, info->version);
path = _alpm_local_db_pkgpath(db, info, "desc");
if(!path || (fp = fopen(path, "w")) == NULL) {
@@ -761,44 +805,21 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq
fprintf(fp, "%%DESC%%\n"
"%s\n\n", info->desc);
}
- if(info->groups) {
- fputs("%GROUPS%\n", fp);
- for(lp = info->groups; lp; lp = lp->next) {
- fprintf(fp, "%s\n", (char *)lp->data);
- }
- fprintf(fp, "\n");
- }
- if(info->replaces) {
- fputs("%REPLACES%\n", fp);
- for(lp = info->replaces; lp; lp = lp->next) {
- char *depstring = alpm_dep_compute_string(lp->data);
- fprintf(fp, "%s\n", depstring);
- free(depstring);
- }
- fprintf(fp, "\n");
- }
if(info->url) {
fprintf(fp, "%%URL%%\n"
"%s\n\n", info->url);
}
- if(info->licenses) {
- fputs("%LICENSE%\n", fp);
- for(lp = info->licenses; lp; lp = lp->next) {
- fprintf(fp, "%s\n", (char *)lp->data);
- }
- fprintf(fp, "\n");
- }
if(info->arch) {
fprintf(fp, "%%ARCH%%\n"
"%s\n\n", info->arch);
}
if(info->builddate) {
fprintf(fp, "%%BUILDDATE%%\n"
- "%ld\n\n", info->builddate);
+ "%jd\n\n", (intmax_t)info->builddate);
}
if(info->installdate) {
fprintf(fp, "%%INSTALLDATE%%\n"
- "%ld\n\n", info->installdate);
+ "%jd\n\n", (intmax_t)info->installdate);
}
if(info->packager) {
fprintf(fp, "%%PACKAGER%%\n"
@@ -813,41 +834,45 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq
fprintf(fp, "%%REASON%%\n"
"%u\n\n", info->reason);
}
- if(info->depends) {
- fputs("%DEPENDS%\n", fp);
- for(lp = info->depends; lp; lp = lp->next) {
- char *depstring = alpm_dep_compute_string(lp->data);
- fprintf(fp, "%s\n", depstring);
- free(depstring);
+ if(info->groups) {
+ fputs("%GROUPS%\n", fp);
+ for(lp = info->groups; lp; lp = lp->next) {
+ fputs(lp->data, fp);
+ fputc('\n', fp);
+ }
+ fputc('\n', fp);
+ }
+ if(info->licenses) {
+ fputs("%LICENSE%\n", fp);
+ for(lp = info->licenses; lp; lp = lp->next) {
+ fputs(lp->data, fp);
+ fputc('\n', fp);
}
- fprintf(fp, "\n");
+ fputc('\n', fp);
}
- if(info->optdepends) {
- fputs("%OPTDEPENDS%\n", fp);
- for(lp = info->optdepends; lp; lp = lp->next) {
- fprintf(fp, "%s\n", (char *)lp->data);
+ if(info->validation) {
+ fputs("%VALIDATION%\n", fp);
+ if(info->validation & ALPM_PKG_VALIDATION_NONE) {
+ fputs("none\n", fp);
+ }
+ if(info->validation & ALPM_PKG_VALIDATION_MD5SUM) {
+ fputs("md5\n", fp);
}
- fprintf(fp, "\n");
- }
- if(info->conflicts) {
- fputs("%CONFLICTS%\n", fp);
- for(lp = info->conflicts; lp; lp = lp->next) {
- char *depstring = alpm_dep_compute_string(lp->data);
- fprintf(fp, "%s\n", depstring);
- free(depstring);
+ if(info->validation & ALPM_PKG_VALIDATION_SHA256SUM) {
+ fputs("sha256\n", fp);
}
- fprintf(fp, "\n");
- }
- if(info->provides) {
- fputs("%PROVIDES%\n", fp);
- for(lp = info->provides; lp; lp = lp->next) {
- char *depstring = alpm_dep_compute_string(lp->data);
- fprintf(fp, "%s\n", depstring);
- free(depstring);
+ if(info->validation & ALPM_PKG_VALIDATION_SIGNATURE) {
+ fputs("pgp\n", fp);
}
- fprintf(fp, "\n");
+ fputc('\n', fp);
}
+ write_deps(fp, "%REPLACES%", info->replaces);
+ write_deps(fp, "%DEPENDS%", info->depends);
+ write_deps(fp, "%OPTDEPENDS%", info->optdepends);
+ write_deps(fp, "%CONFLICTS%", info->conflicts);
+ write_deps(fp, "%PROVIDES%", info->provides);
+
fclose(fp);
fp = NULL;
}
@@ -855,7 +880,8 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq
/* FILES */
if(inforeq & INFRQ_FILES) {
char *path;
- _alpm_log(db->handle, ALPM_LOG_DEBUG, "writing %s-%s FILES information back to db\n",
+ _alpm_log(db->handle, ALPM_LOG_DEBUG,
+ "writing %s-%s FILES information back to db\n",
info->name, info->version);
path = _alpm_local_db_pkgpath(db, info, "files");
if(!path || (fp = fopen(path, "w")) == NULL) {
@@ -868,20 +894,21 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq
free(path);
if(info->files.count) {
size_t i;
- fprintf(fp, "%%FILES%%\n");
+ fputs("%FILES%\n", fp);
for(i = 0; i < info->files.count; i++) {
const alpm_file_t *file = info->files.files + i;
- fprintf(fp, "%s\n", file->name);
+ fputs(file->name, fp);
+ fputc('\n', fp);
}
- fprintf(fp, "\n");
+ fputc('\n', fp);
}
if(info->backup) {
- fprintf(fp, "%%BACKUP%%\n");
+ fputs("%BACKUP%\n", fp);
for(lp = info->backup; lp; lp = lp->next) {
const alpm_backup_t *backup = lp->data;
fprintf(fp, "%s\t%s\n", backup->name, backup->hash);
}
- fprintf(fp, "\n");
+ fputc('\n', fp);
}
fclose(fp);
fp = NULL;
@@ -903,17 +930,71 @@ cleanup:
int _alpm_local_db_remove(alpm_db_t *db, alpm_pkg_t *info)
{
int ret = 0;
- char *pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
+ DIR *dirp;
+ struct dirent *dp;
+ char *pkgpath;
+ size_t pkgpath_len;
- /* TODO explicit file removes and then an rmdir? */
- ret = _alpm_rmrf(pkgpath);
- free(pkgpath);
- if(ret != 0) {
+ pkgpath = _alpm_local_db_pkgpath(db, info, NULL);
+ if(!pkgpath) {
+ return -1;
+ }
+ pkgpath_len = strlen(pkgpath);
+
+ dirp = opendir(pkgpath);
+ if(!dirp) {
+ return -1;
+ }
+ /* go through the local DB entry, removing the files within, which we know
+ * are not nested directories of any kind. */
+ for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) {
+ char name[PATH_MAX];
+ if(pkgpath_len + strlen(dp->d_name) + 2 > PATH_MAX) {
+ /* file path is too long to remove, hmm. */
+ ret = -1;
+ } else {
+ sprintf(name, "%s/%s", pkgpath, dp->d_name);
+ if(unlink(name)) {
+ ret = -1;
+ }
+ }
+ }
+ }
+ closedir(dirp);
+
+ /* after removing all enclosed files, we can remove the directory itself. */
+ if(rmdir(pkgpath)) {
ret = -1;
}
+ free(pkgpath);
return ret;
}
+int SYMEXPORT alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason)
+{
+ ASSERT(pkg != NULL, return -1);
+ ASSERT(pkg->origin == ALPM_PKG_FROM_LOCALDB,
+ RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
+ ASSERT(pkg->origin_data.db == pkg->handle->db_local,
+ RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
+
+ _alpm_log(pkg->handle, ALPM_LOG_DEBUG,
+ "setting install reason %u for %s\n", reason, pkg->name);
+ if(alpm_pkg_get_reason(pkg) == reason) {
+ /* we are done */
+ return 0;
+ }
+ /* set reason (in pkgcache) */
+ pkg->reason = reason;
+ /* write DESC */
+ if(_alpm_local_db_write(pkg->handle->db_local, pkg, INFRQ_DESC)) {
+ RET_ERR(pkg->handle, ALPM_ERR_DB_WRITE, -1);
+ }
+
+ return 0;
+}
+
struct db_operations local_db_ops = {
.validate = local_db_validate,
.populate = local_db_populate,
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 93b762a1..8c5b2d16 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -1,7 +1,7 @@
/*
* be_package.c : backend for packages
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,11 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
/* libarchive */
#include <archive.h>
@@ -35,7 +36,13 @@
#include "log.h"
#include "handle.h"
#include "package.h"
-#include "deps.h" /* _alpm_splitdep */
+#include "deps.h"
+#include "filelist.h"
+
+struct package_changelog {
+ struct archive *archive;
+ int fd;
+};
/**
* Open a package changelog for reading. Similar to fopen in functionality,
@@ -47,31 +54,38 @@ static void *_package_changelog_open(alpm_pkg_t *pkg)
{
ASSERT(pkg != NULL, return NULL);
- struct archive *archive = NULL;
+ struct package_changelog *changelog;
+ struct archive *archive;
struct archive_entry *entry;
const char *pkgfile = pkg->origin_data.file;
+ struct stat buf;
+ int fd;
- if((archive = archive_read_new()) == NULL) {
- RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, NULL);
- }
-
- archive_read_support_compression_all(archive);
- archive_read_support_format_all(archive);
-
- if(archive_read_open_filename(archive, pkgfile,
- ALPM_BUFFER_SIZE) != ARCHIVE_OK) {
- RET_ERR(pkg->handle, ALPM_ERR_PKG_OPEN, NULL);
+ fd = _alpm_open_archive(pkg->handle, pkgfile, &buf,
+ &archive, ALPM_ERR_PKG_OPEN);
+ if(fd < 0) {
+ return NULL;
}
while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
const char *entry_name = archive_entry_pathname(entry);
if(strcmp(entry_name, ".CHANGELOG") == 0) {
- return archive;
+ changelog = malloc(sizeof(struct package_changelog));
+ if(!changelog) {
+ pkg->handle->pm_errno = ALPM_ERR_MEMORY;
+ archive_read_finish(archive);
+ CLOSE(fd);
+ return NULL;
+ }
+ changelog->archive = archive;
+ changelog->fd = fd;
+ return changelog;
}
}
/* we didn't find a changelog */
archive_read_finish(archive);
+ CLOSE(fd);
errno = ENOENT;
return NULL;
@@ -89,7 +103,8 @@ static void *_package_changelog_open(alpm_pkg_t *pkg)
static size_t _package_changelog_read(void *ptr, size_t size,
const alpm_pkg_t UNUSED *pkg, void *fp)
{
- ssize_t sret = archive_read_data((struct archive *)fp, ptr, size);
+ struct package_changelog *changelog = fp;
+ ssize_t sret = archive_read_data(changelog->archive, ptr, size);
/* Report error (negative values) */
if(sret < 0) {
RET_ERR(pkg->handle, ALPM_ERR_LIBARCHIVE, 0);
@@ -107,7 +122,12 @@ static size_t _package_changelog_read(void *ptr, size_t size,
*/
static int _package_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp)
{
- return archive_read_finish((struct archive *)fp);
+ int ret;
+ struct package_changelog *changelog = fp;
+ ret = archive_read_finish(changelog->archive);
+ CLOSE(changelog->fd);
+ free(changelog);
+ return ret;
}
/** Package file operations struct accessor. We implement this as a method
@@ -149,21 +169,24 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
/* loop until we reach EOF or other error */
while((ret = _alpm_archive_fgets(a, &buf)) == ARCHIVE_OK) {
- size_t len = _alpm_strip_newline(buf.line);
+ size_t len = _alpm_strip_newline(buf.line, buf.real_line_size);
linenum++;
- if(len == 0 || buf.line[0] == '#') {
+ key = buf.line;
+ if(len == 0 || key[0] == '#') {
continue;
}
- ptr = buf.line;
- key = strsep(&ptr, "=");
- if(key == NULL || ptr == NULL) {
- _alpm_log(handle, ALPM_LOG_DEBUG, "%s: syntax error in description file line %d\n",
- newpkg->name ? newpkg->name : "error", linenum);
+ /* line is always in this format: "key = value"
+ * we can be sure the " = " exists, so look for that */
+ ptr = memchr(key, ' ', len);
+ if(!ptr || (size_t)(ptr - key + 2) > len || memcmp(ptr, " = ", 3) != 0) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "%s: syntax error in description file line %d\n",
+ newpkg->name ? newpkg->name : "error", linenum);
} else {
- key = _alpm_strtrim(key);
- while(*ptr == ' ') ptr++;
- ptr = _alpm_strtrim(ptr);
+ /* NULL the end of the key portion, move ptr to start of value */
+ *ptr = '\0';
+ ptr += 3;
if(strcmp(key, "pkgname") == 0) {
STRDUP(newpkg->name, ptr, return -1);
newpkg->name_hash = _alpm_hash_sdbm(newpkg->name);
@@ -192,7 +215,8 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
alpm_depend_t *dep = _alpm_splitdep(ptr);
newpkg->depends = alpm_list_add(newpkg->depends, dep);
} else if(strcmp(key, "optdepend") == 0) {
- newpkg->optdepends = alpm_list_add(newpkg->optdepends, strdup(ptr));
+ alpm_depend_t *optdep = _alpm_splitdep(ptr);
+ newpkg->optdepends = alpm_list_add(newpkg->optdepends, optdep);
} else if(strcmp(key, "conflict") == 0) {
alpm_depend_t *conflict = _alpm_splitdep(ptr);
newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict);
@@ -225,53 +249,6 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
return 0;
}
-static void files_merge(alpm_file_t a[], alpm_file_t b[], alpm_file_t c[],
- size_t m, size_t n)
-{
- size_t i = 0, j = 0, k = 0;
- while(i < m && j < n) {
- if(strcmp(a[i].name, b[j].name) < 0) {
- c[k++] = a[i++];
- } else {
- c[k++] = b[j++];
- }
- }
- while(i < m) {
- c[k++] = a[i++];
- }
- while(j < n) {
- c[k++] = b[j++];
- }
-}
-
-static alpm_file_t *files_msort(alpm_file_t *files, size_t n)
-{
- alpm_file_t *work;
- size_t blocksize = 1;
-
- CALLOC(work, n, sizeof(alpm_file_t), return NULL);
-
- for(blocksize = 1; blocksize < n; blocksize *= 2) {
- size_t i, max_extent = 0;
- for(i = 0; i < n - blocksize; i += 2 * blocksize) {
- /* this limits our actual merge to the length of the array, since we will
- * not likely be a perfect power of two. */
- size_t right_blocksize = blocksize;
- if(i + blocksize * 2 > n) {
- right_blocksize = n - i - blocksize;
- }
- files_merge(files + i, files + i + blocksize, work + i,
- blocksize, right_blocksize);
- max_extent = i + blocksize + right_blocksize;
- }
- /* ensure we only copy what we actually touched on this merge pass,
- * no more, no less */
- memcpy(files, work, max_extent * sizeof(alpm_file_t));
- }
- free(work);
- return files;
-}
-
/**
* Validate a package.
* @param handle the context handle
@@ -280,11 +257,12 @@ static alpm_file_t *files_msort(alpm_file_t *files, size_t n)
* sha256sum, and/or base64 signature)
* @param level the required level of signature verification
* @param sigdata signature data from the package to pass back
+ * @param validation successful validations performed on the package file
* @return 0 if package is fully valid, -1 and pm_errno otherwise
*/
int _alpm_pkg_validate_internal(alpm_handle_t *handle,
const char *pkgfile, alpm_pkg_t *syncpkg, alpm_siglevel_t level,
- alpm_siglist_t **sigdata)
+ alpm_siglist_t **sigdata, alpm_pkgvalidation_t *validation)
{
int has_sig;
handle->pm_errno = 0;
@@ -294,8 +272,15 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
}
/* attempt to access the package file, ensure it exists */
- if(access(pkgfile, R_OK) != 0) {
- RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, -1);
+ if(_alpm_access(handle, NULL, pkgfile, R_OK) != 0) {
+ if(errno == ENOENT) {
+ handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND;
+ } else if(errno == EACCES) {
+ handle->pm_errno = ALPM_ERR_BADPERMS;
+ } else {
+ handle->pm_errno = ALPM_ERR_PKG_OPEN;
+ }
+ return -1;
}
/* can we get away with skipping checksums? */
@@ -316,17 +301,23 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
if(syncpkg->md5sum && !syncpkg->sha256sum) {
_alpm_log(handle, ALPM_LOG_DEBUG, "md5sum: %s\n", syncpkg->md5sum);
_alpm_log(handle, ALPM_LOG_DEBUG, "checking md5sum for %s\n", pkgfile);
- if(_alpm_test_checksum(pkgfile, syncpkg->md5sum, ALPM_CSUM_MD5) != 0) {
+ if(_alpm_test_checksum(pkgfile, syncpkg->md5sum, ALPM_PKG_VALIDATION_MD5SUM) != 0) {
RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1);
}
+ if(validation) {
+ *validation |= ALPM_PKG_VALIDATION_MD5SUM;
+ }
}
if(syncpkg->sha256sum) {
_alpm_log(handle, ALPM_LOG_DEBUG, "sha256sum: %s\n", syncpkg->sha256sum);
_alpm_log(handle, ALPM_LOG_DEBUG, "checking sha256sum for %s\n", pkgfile);
- if(_alpm_test_checksum(pkgfile, syncpkg->sha256sum, ALPM_CSUM_SHA256) != 0) {
+ if(_alpm_test_checksum(pkgfile, syncpkg->sha256sum, ALPM_PKG_VALIDATION_SHA256SUM) != 0) {
RET_ERR(handle, ALPM_ERR_PKG_INVALID_CHECKSUM, -1);
}
+ if(validation) {
+ *validation |= ALPM_PKG_VALIDATION_SHA256SUM;
+ }
}
}
@@ -340,6 +331,13 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
handle->pm_errno = ALPM_ERR_PKG_INVALID_SIG;
return -1;
}
+ if(validation && has_sig) {
+ *validation |= ALPM_PKG_VALIDATION_SIGNATURE;
+ }
+ }
+
+ if (validation && !*validation) {
+ *validation = ALPM_PKG_VALIDATION_NONE;
}
return 0;
@@ -355,10 +353,10 @@ int _alpm_pkg_validate_internal(alpm_handle_t *handle,
alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
const char *pkgfile, int full)
{
- int ret, config = 0;
+ int ret, fd, config = 0;
struct archive *archive;
struct archive_entry *entry;
- alpm_pkg_t *newpkg = NULL;
+ alpm_pkg_t *newpkg;
struct stat st;
size_t files_size = 0;
@@ -366,33 +364,26 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL);
}
- /* attempt to stat the package file, ensure it exists */
- if(stat(pkgfile, &st) == 0) {
- newpkg = _alpm_pkg_new();
- if(newpkg == NULL) {
- RET_ERR(handle, ALPM_ERR_MEMORY, NULL);
+ fd = _alpm_open_archive(handle, pkgfile, &st, &archive, ALPM_ERR_PKG_OPEN);
+ if(fd < 0) {
+ if(errno == ENOENT) {
+ handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND;
+ } else if(errno == EACCES) {
+ handle->pm_errno = ALPM_ERR_BADPERMS;
+ } else {
+ handle->pm_errno = ALPM_ERR_PKG_OPEN;
}
- newpkg->filename = strdup(pkgfile);
- newpkg->size = st.st_size;
- } else {
- /* couldn't stat the pkgfile, return an error */
- RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, NULL);
- }
-
- /* try to create an archive object to read in the package */
- if((archive = archive_read_new()) == NULL) {
- _alpm_pkg_free(newpkg);
- RET_ERR(handle, ALPM_ERR_LIBARCHIVE, NULL);
+ return NULL;
}
- archive_read_support_compression_all(archive);
- archive_read_support_format_all(archive);
-
- if(archive_read_open_filename(archive, pkgfile,
- ALPM_BUFFER_SIZE) != ARCHIVE_OK) {
- handle->pm_errno = ALPM_ERR_PKG_OPEN;
+ newpkg = _alpm_pkg_new();
+ if(newpkg == NULL) {
+ handle->pm_errno = ALPM_ERR_MEMORY;
goto error;
}
+ STRDUP(newpkg->filename, pkgfile,
+ handle->pm_errno = ALPM_ERR_MEMORY; goto error);
+ newpkg->size = st.st_size;
_alpm_log(handle, ALPM_LOG_DEBUG, "starting package load for %s\n", pkgfile);
@@ -439,7 +430,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
newfiles = realloc(newpkg->files.files,
sizeof(alpm_file_t) * files_size);
if(!newfiles) {
- ALLOC_FAIL(sizeof(alpm_file_t) * files_size);
+ _alpm_alloc_fail(sizeof(alpm_file_t) * files_size);
goto error;
}
/* ensure all new memory is zeroed out, in both the initial
@@ -481,13 +472,15 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
}
archive_read_finish(archive);
+ CLOSE(fd);
/* internal fields for package struct */
- newpkg->origin = PKG_FROM_FILE;
+ newpkg->origin = ALPM_PKG_FROM_FILE;
newpkg->origin_data.file = strdup(pkgfile);
newpkg->ops = get_file_pkg_ops();
newpkg->handle = handle;
newpkg->infolevel = INFRQ_BASE | INFRQ_DESC | INFRQ_SCRIPTLET;
+ newpkg->validation = ALPM_PKG_VALIDATION_NONE;
if(full) {
if(newpkg->files.files) {
@@ -497,8 +490,9 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
/* "checking for conflicts" requires a sorted list, ensure that here */
_alpm_log(handle, ALPM_LOG_DEBUG,
"sorting package filelist for %s\n", pkgfile);
- newpkg->files.files = files_msort(newpkg->files.files,
- newpkg->files.count);
+
+ qsort(newpkg->files.files, newpkg->files.count,
+ sizeof(alpm_file_t), _alpm_files_cmp);
}
newpkg->infolevel |= INFRQ_FILES;
}
@@ -510,6 +504,9 @@ pkg_invalid:
error:
_alpm_pkg_free(newpkg);
archive_read_finish(archive);
+ if(fd >= 0) {
+ CLOSE(fd);
+ }
return NULL;
}
@@ -517,10 +514,13 @@ error:
int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full,
alpm_siglevel_t level, alpm_pkg_t **pkg)
{
+ alpm_pkgvalidation_t validation = 0;
+
CHECK_HANDLE(handle, return -1);
ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
- if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL) == -1) {
+ if(_alpm_pkg_validate_internal(handle, filename, NULL, level, NULL,
+ &validation) == -1) {
/* pm_errno is set by pkg_validate */
return -1;
}
@@ -529,6 +529,7 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful
/* pm_errno is set by pkg_load */
return -1;
}
+ (*pkg)->validation = validation;
return 0;
}
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index 3c990246..6bac6fbf 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -1,7 +1,7 @@
/*
* be_sync.c : backend for sync databases
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,10 +18,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <errno.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include <unistd.h>
/* libarchive */
@@ -86,7 +86,7 @@ static int sync_db_validate(alpm_db_t *db)
}
/* we can skip any validation if the database doesn't exist */
- if(access(dbpath, R_OK) != 0 && errno == ENOENT) {
+ if(_alpm_access(db->handle, NULL, dbpath, R_OK) != 0 && errno == ENOENT) {
db->status &= ~DB_STATUS_EXISTS;
db->status |= DB_STATUS_MISSING;
_alpm_log(db->handle, ALPM_LOG_WARNING,
@@ -142,7 +142,7 @@ valid:
*
* Example:
* @code
- * alpm_list_t *syncs = alpm_option_get_syncdbs();
+ * alpm_list_t *syncs = alpm_get_syncdbs();
* for(i = syncs; i; i = alpm_list_next(i)) {
* alpm_db_t *db = alpm_list_getdata(i);
* result = alpm_db_update(0, db);
@@ -212,6 +212,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
/* print server + filename into a buffer */
len = strlen(server) + strlen(db->treename) + 5;
+ /* TODO fix leak syncpath and umask unset */
MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
snprintf(payload.fileurl, len, "%s/%s.db", server, db->treename);
payload.handle = handle;
@@ -234,6 +235,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
/* if we downloaded a DB, we want the .sig from the same server */
/* print server + filename into a buffer (leave space for .sig) */
len = strlen(server) + strlen(db->treename) + 9;
+ /* TODO fix leak syncpath and umask unset */
MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
snprintf(payload.fileurl, len, "%s/%s.db.sig", server, db->treename);
payload.handle = handle;
@@ -294,6 +296,29 @@ cleanup:
static int sync_db_read(alpm_db_t *db, struct archive *archive,
struct archive_entry *entry, alpm_pkg_t **likely_pkg);
+static alpm_pkgvalidation_t _sync_get_validation(alpm_pkg_t *pkg)
+{
+ if(pkg->validation) {
+ return pkg->validation;
+ }
+
+ if(pkg->md5sum) {
+ pkg->validation |= ALPM_PKG_VALIDATION_MD5SUM;
+ }
+ if(pkg->sha256sum) {
+ pkg->validation |= ALPM_PKG_VALIDATION_SHA256SUM;
+ }
+ if(pkg->base64_sig) {
+ pkg->validation |= ALPM_PKG_VALIDATION_SIGNATURE;
+ }
+
+ if(!pkg->validation) {
+ pkg->validation |= ALPM_PKG_VALIDATION_NONE;
+ }
+
+ return pkg->validation;
+}
+
static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,
const char **entry_filename, alpm_pkg_t *likely_pkg)
{
@@ -316,7 +341,8 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,
return NULL;
}
- if(likely_pkg && strcmp(likely_pkg->name, pkgname) == 0) {
+ if(likely_pkg && pkgname_hash == likely_pkg->name_hash
+ && strcmp(likely_pkg->name, pkgname) == 0) {
pkg = likely_pkg;
} else {
pkg = _alpm_pkghash_find(db->pkgcache, pkgname);
@@ -331,9 +357,10 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,
pkg->version = pkgver;
pkg->name_hash = pkgname_hash;
- pkg->origin = PKG_FROM_SYNCDB;
+ pkg->origin = ALPM_PKG_FROM_SYNCDB;
pkg->origin_data.db = db;
pkg->ops = &default_pkg_ops;
+ pkg->ops->get_validation = _sync_get_validation;
pkg->handle = db->handle;
/* add to the collection */
@@ -348,61 +375,38 @@ static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,
return pkg;
}
-/*
- * This is the data table used to generate the estimating function below.
- * "Weighted Avg" means averaging the bottom table values; thus each repo, big
- * or small, will have equal influence. "Unweighted Avg" means averaging the
- * sums of the top table columns, thus each package has equal influence. The
- * final values are calculated by (surprise) averaging the averages, because
- * why the hell not.
- *
- * Database Pkgs tar bz2 gz xz
- * community 2096 5294080 256391 421227 301296
- * core 180 460800 25257 36850 29356
- * extra 2606 6635520 294647 470818 339392
- * multilib 126 327680 16120 23261 18732
- * testing 76 204800 10902 14348 12100
- *
- * Bytes Per Package
- * community 2096 2525.80 122.32 200.97 143.75
- * core 180 2560.00 140.32 204.72 163.09
- * extra 2606 2546.25 113.06 180.67 130.23
- * multilib 126 2600.63 127.94 184.61 148.67
- * testing 76 2694.74 143.45 188.79 159.21
-
- * Weighted Avg 2585.48 129.42 191.95 148.99
- * Unweighted Avg 2543.39 118.74 190.16 137.93
- * Average of Avgs 2564.44 124.08 191.06 143.46
- */
+/* This function doesn't work as well as one might think, as size of database
+ * entries varies considerably. Adding signatures nearly doubles the size of a
+ * single entry; deltas also can make for large variations in size. These
+ * current values are heavily influenced by Arch Linux; databases with no
+ * deltas and a single signature per package. */
static size_t estimate_package_count(struct stat *st, struct archive *archive)
{
- unsigned int per_package;
+ int per_package;
switch(archive_compression(archive)) {
case ARCHIVE_COMPRESSION_NONE:
- per_package = 2564;
+ per_package = 3015;
break;
case ARCHIVE_COMPRESSION_GZIP:
- per_package = 191;
+ case ARCHIVE_COMPRESSION_COMPRESS:
+ per_package = 464;
break;
case ARCHIVE_COMPRESSION_BZIP2:
- per_package = 124;
- break;
- case ARCHIVE_COMPRESSION_COMPRESS:
- per_package = 193;
+ per_package = 394;
break;
case ARCHIVE_COMPRESSION_LZMA:
case ARCHIVE_COMPRESSION_XZ:
- per_package = 143;
+ per_package = 400;
break;
#ifdef ARCHIVE_COMPRESSION_UU
case ARCHIVE_COMPRESSION_UU:
- per_package = 3543;
+ per_package = 3015 * 4 / 3;
break;
#endif
default:
/* assume it is at least somewhat compressed */
- per_package = 200;
+ per_package = 500;
}
return (size_t)((st->st_size / per_package) + 1);
}
@@ -411,7 +415,7 @@ static int sync_db_populate(alpm_db_t *db)
{
const char *dbpath;
size_t est_count;
- int count = 0;
+ int count, fd;
struct stat buf;
struct archive *archive;
struct archive_entry *entry;
@@ -423,38 +427,24 @@ static int sync_db_populate(alpm_db_t *db)
if(db->status & DB_STATUS_MISSING) {
RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1);
}
-
- if((archive = archive_read_new()) == NULL) {
- RET_ERR(db->handle, ALPM_ERR_LIBARCHIVE, -1);
- }
-
- archive_read_support_compression_all(archive);
- archive_read_support_format_all(archive);
-
dbpath = _alpm_db_path(db);
if(!dbpath) {
/* pm_errno set in _alpm_db_path() */
return -1;
}
- _alpm_log(db->handle, ALPM_LOG_DEBUG, "opening database archive %s\n", dbpath);
-
- if(archive_read_open_filename(archive, dbpath,
- ALPM_BUFFER_SIZE) != ARCHIVE_OK) {
- _alpm_log(db->handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), dbpath,
- archive_error_string(archive));
- archive_read_finish(archive);
- RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
- }
- if(stat(dbpath, &buf) != 0) {
- RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
+ fd = _alpm_open_archive(db->handle, dbpath, &buf,
+ &archive, ALPM_ERR_DB_OPEN);
+ if(fd < 0) {
+ return -1;
}
est_count = estimate_package_count(&buf, archive);
- /* initialize hash at 66% full */
- db->pkgcache = _alpm_pkghash_create(est_count * 3 / 2);
+ db->pkgcache = _alpm_pkghash_create(est_count);
if(db->pkgcache == NULL) {
- RET_ERR(db->handle, ALPM_ERR_MEMORY, -1);
+ db->handle->pm_errno = ALPM_ERR_MEMORY;
+ count = -1;
+ goto cleanup;
}
while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
@@ -473,21 +463,26 @@ static int sync_db_populate(alpm_db_t *db)
}
count = alpm_list_count(db->pkgcache->list);
-
if(count > 0) {
- db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp);
+ db->pkgcache->list = alpm_list_msort(db->pkgcache->list,
+ (size_t)count, _alpm_pkg_cmp);
}
- archive_read_finish(archive);
- _alpm_log(db->handle, ALPM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n",
+ _alpm_log(db->handle, ALPM_LOG_DEBUG,
+ "added %d packages to package cache for db '%s'\n",
count, db->treename);
+cleanup:
+ archive_read_finish(archive);
+ if(fd >= 0) {
+ CLOSE(fd);
+ }
return count;
}
#define READ_NEXT() do { \
if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
line = buf.line; \
- _alpm_strip_newline(line); \
+ _alpm_strip_newline(line, buf.real_line_size); \
} while(0)
#define READ_AND_STORE(f) do { \
@@ -498,14 +493,14 @@ static int sync_db_populate(alpm_db_t *db)
#define READ_AND_STORE_ALL(f) do { \
char *linedup; \
if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
- if(_alpm_strip_newline(buf.line) == 0) break; \
+ if(_alpm_strip_newline(buf.line, buf.real_line_size) == 0) break; \
STRDUP(linedup, buf.line, goto error); \
f = alpm_list_add(f, linedup); \
} while(1) /* note the while(1) and not (0) */
#define READ_AND_SPLITDEP(f) do { \
if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
- if(_alpm_strip_newline(buf.line) == 0) break; \
+ if(_alpm_strip_newline(buf.line, buf.real_line_size) == 0) break; \
f = alpm_list_add(f, _alpm_splitdep(line)); \
} while(1) /* note the while(1) and not (0) */
@@ -544,7 +539,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
int ret;
while((ret = _alpm_archive_fgets(archive, &buf)) == ARCHIVE_OK) {
char *line = buf.line;
- if(_alpm_strip_newline(line) == 0) {
+ if(_alpm_strip_newline(line, buf.real_line_size) == 0) {
/* length of stripped line was zero */
continue;
}
@@ -595,7 +590,19 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
} else if(strcmp(line, "%DEPENDS%") == 0) {
READ_AND_SPLITDEP(pkg->depends);
} else if(strcmp(line, "%OPTDEPENDS%") == 0) {
- READ_AND_STORE_ALL(pkg->optdepends);
+ READ_AND_SPLITDEP(pkg->optdepends);
+ } else if(strcmp(line, "%MAKEDEPENDS%") == 0) {
+ /* currently unused */
+ while(1) {
+ READ_NEXT();
+ if(strlen(line) == 0) break;
+ }
+ } else if(strcmp(line, "%CHECKDEPENDS%") == 0) {
+ /* currently unused */
+ while(1) {
+ READ_NEXT();
+ if(strlen(line) == 0) break;
+ }
} else if(strcmp(line, "%CONFLICTS%") == 0) {
READ_AND_SPLITDEP(pkg->conflicts);
} else if(strcmp(line, "%PROVIDES%") == 0) {
@@ -605,7 +612,8 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
while(1) {
READ_NEXT();
if(strlen(line) == 0) break;
- pkg->deltas = alpm_list_add(pkg->deltas, _alpm_delta_parse(line));
+ pkg->deltas = alpm_list_add(pkg->deltas,
+ _alpm_delta_parse(db->handle, line));
}
}
}
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 6bfd256f..ccfe990c 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -1,7 +1,7 @@
/*
* conflict.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org>
@@ -22,8 +22,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -40,6 +38,7 @@
#include "util.h"
#include "log.h"
#include "deps.h"
+#include "filelist.h"
static alpm_conflict_t *conflict_new(alpm_pkg_t *pkg1, alpm_pkg_t *pkg2,
alpm_depend_t *reason)
@@ -215,67 +214,6 @@ alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_handle_t *handle,
return _alpm_innerconflicts(handle, pkglist);
}
-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!
- * When done, free the list but NOT the contained data.
- *
- * Operations:
- * DIFFERENCE - a difference operation is performed. filesA - filesB.
- * INTERSECT - an intersection operation is performed. filesA & filesB.
- */
-static alpm_list_t *filelist_operation(alpm_filelist_t *filesA,
- alpm_filelist_t *filesB, int operation)
-{
- alpm_list_t *ret = NULL;
- size_t ctrA = 0, ctrB = 0;
-
- while(ctrA < filesA->count && ctrB < filesB->count) {
- alpm_file_t *fileA = filesA->files + ctrA;
- alpm_file_t *fileB = filesB->files + ctrB;
- const char *strA = fileA->name;
- const char *strB = fileB->name;
- /* skip directories, we don't care about them */
- if(strA[strlen(strA)-1] == '/') {
- ctrA++;
- } else if(strB[strlen(strB)-1] == '/') {
- ctrB++;
- } else {
- int cmp = strcmp(strA, strB);
- if(cmp < 0) {
- if(operation == DIFFERENCE) {
- /* item only in filesA, qualifies as a difference */
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- } else if(cmp > 0) {
- ctrB++;
- } else {
- if(operation == INTERSECT) {
- /* item in both, qualifies as an intersect */
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- ctrB++;
- }
- }
- }
-
- /* if doing a difference, ensure we have completely emptied pA */
- while(operation == DIFFERENCE && ctrA < filesA->count) {
- alpm_file_t *fileA = filesA->files + ctrA;
- const char *strA = fileA->name;
- /* skip directories */
- if(strA[strlen(strA)-1] != '/') {
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- }
-
- return ret;
-}
-
/* Adds alpm_fileconflict_t to a conflicts list. Pass the conflicts list, the
* conflicting file path, and either two packages or one package and NULL.
*/
@@ -314,20 +252,6 @@ void _alpm_fileconflict_free(alpm_fileconflict_t *conflict)
FREE(conflict);
}
-const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,
- const char *name)
-{
- size_t i;
- const alpm_file_t *file = filelist->files;
- for(i = 0; i < filelist->count; i++) {
- if(strcmp(file->name, name) == 0) {
- return file;
- }
- file++;
- }
- return NULL;
-}
-
static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
alpm_pkg_t *pkg)
{
@@ -340,7 +264,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
const char *root = handle->root;
/* check directory is actually in package - used for subdirectory checks */
- if(!_alpm_filelist_contains(alpm_pkg_get_files(pkg), dirpath)) {
+ if(!alpm_filelist_contains(alpm_pkg_get_files(pkg), dirpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"directory %s not in package %s\n", dirpath, pkg->name);
return 0;
@@ -358,7 +282,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
continue;
}
- if(_alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"file %s also in package %s\n", dirpath,
((alpm_pkg_t*)i->data)->name);
@@ -392,7 +316,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
return 0;
}
} else {
- if(_alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) {
continue;
} else {
closedir(dir);
@@ -410,16 +334,19 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
* 1: check every target against every target
* 2: check every target against the filesystem */
alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
- alpm_list_t *upgrade, alpm_list_t *remove)
+ alpm_list_t *upgrade, alpm_list_t *rem)
{
alpm_list_t *i, *conflicts = NULL;
size_t numtargs = alpm_list_count(upgrade);
size_t current;
+ size_t rootlen;
if(!upgrade) {
return NULL;
}
+ rootlen = strlen(handle->root);
+
/* TODO this whole function needs a huge change, which hopefully will
* be possible with real transactions. Right now we only do half as much
* here as we do when we actually extract files in add.c with our 12
@@ -440,8 +367,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
for(j = i->next; j; j = j->next) {
alpm_list_t *common_files;
alpm_pkg_t *p2 = j->data;
- common_files = filelist_operation(alpm_pkg_get_files(p1),
- alpm_pkg_get_files(p2), INTERSECT);
+ common_files = _alpm_filelist_intersection(alpm_pkg_get_files(p1),
+ alpm_pkg_get_files(p2));
if(common_files) {
alpm_list_t *k;
@@ -473,8 +400,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
if(dbpkg) {
alpm_list_t *difference;
/* older ver of package currently installed */
- difference = filelist_operation(alpm_pkg_get_files(p1),
- alpm_pkg_get_files(dbpkg), DIFFERENCE);
+ difference = _alpm_filelist_difference(alpm_pkg_get_files(p1),
+ alpm_pkg_get_files(dbpkg));
tmpfiles.count = alpm_list_count(difference);
tmpfiles.files = alpm_list_to_array(difference, tmpfiles.count,
sizeof(alpm_file_t));
@@ -493,8 +420,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
int resolved_conflict = 0;
struct stat lsbuf;
char path[PATH_MAX];
+ size_t pathlen;
- snprintf(path, PATH_MAX, "%s%s", handle->root, filestr);
+ pathlen = snprintf(path, PATH_MAX, "%s%s", handle->root, filestr);
/* stat the file - if it exists, do some checks */
if(_alpm_lstat(path, &lsbuf) != 0) {
@@ -518,15 +446,15 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
/* if we made it to here, we want all subsequent path comparisons to
* not include the trailing slash. This allows things like file ->
* directory replacements. */
- path[strlen(path) - 1] = '\0';
+ path[pathlen - 1] = '\0';
}
- relative_path = path + strlen(handle->root);
+ relative_path = path + rootlen;
/* Check remove list (will we remove the conflicting local file?) */
- for(k = remove; k && !resolved_conflict; k = k->next) {
+ for(k = rem; k && !resolved_conflict; k = k->next) {
alpm_pkg_t *rempkg = k->data;
- if(rempkg && _alpm_filelist_contains(alpm_pkg_get_files(rempkg),
+ if(rempkg && alpm_filelist_contains(alpm_pkg_get_files(rempkg),
relative_path)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"local file will be removed, not a conflict\n");
@@ -543,7 +471,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
alpm_pkg_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_filelist_contains(alpm_pkg_get_files(localp2), filestr)) {
+ if(localp2 && alpm_filelist_contains(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 */
@@ -559,7 +487,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
if(!resolved_conflict && S_ISDIR(lsbuf.st_mode) && dbpkg) {
char *dir = malloc(strlen(filestr) + 2);
sprintf(dir, "%s/", filestr);
- if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"checking if all files in %s belong to %s\n",
dir, dbpkg->name);
@@ -573,17 +501,15 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
* consideration cannot itself be a link, as it might be unowned- path
* components can be safely checked as all directories are "unowned". */
if(!resolved_conflict && dbpkg && !S_ISLNK(lsbuf.st_mode)) {
- char *rpath = calloc(PATH_MAX, sizeof(char));
- const char *relative_rpath;
+ char rpath[PATH_MAX];
if(realpath(path, rpath)) {
- relative_rpath = rpath + strlen(handle->root);
- if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) {
+ const char *relative_rpath = rpath + rootlen;
+ if(alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"package contained the resolved realpath\n");
resolved_conflict = 1;
}
}
- free(rpath);
}
/* is the file unowned and in the backup list of the new package? */
@@ -591,7 +517,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
alpm_list_t *local_pkgs = _alpm_db_get_pkgcache(handle->db_local);
int found = 0;
for(k = local_pkgs; k && !found; k = k->next) {
- if(_alpm_filelist_contains(alpm_pkg_get_files(k->data), filestr)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(k->data), filestr)) {
found = 1;
}
}
@@ -607,7 +533,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
if(handle->pm_errno == ALPM_ERR_MEMORY) {
FREELIST(conflicts);
if(dbpkg) {
- /* only freed if it was generated from filelist_operation() */
+ /* only freed if it was generated from _alpm_filelist_difference() */
free(tmpfiles.files);
}
return NULL;
@@ -615,7 +541,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
}
}
if(dbpkg) {
- /* only freed if it was generated from filelist_operation() */
+ /* only freed if it was generated from _alpm_filelist_difference() */
free(tmpfiles.files);
}
}
diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h
index 8b7471fd..0bfdfd76 100644
--- a/lib/libalpm/conflict.h
+++ b/lib/libalpm/conflict.h
@@ -1,7 +1,7 @@
/*
* conflict.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -33,9 +33,6 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
void _alpm_fileconflict_free(alpm_fileconflict_t *conflict);
-const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,
- const char *name);
-
#endif /* _ALPM_CONFLICT_H */
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index 8688a3cd..953f2af6 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -1,7 +1,7 @@
/*
* db.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
@@ -22,8 +22,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -45,7 +43,7 @@
*/
/** Register a sync database of packages. */
-alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle,
+alpm_db_t SYMEXPORT *alpm_register_syncdb(alpm_handle_t *handle,
const char *treename, alpm_siglevel_t level)
{
/* Sanity checks */
@@ -70,7 +68,7 @@ void _alpm_db_unregister(alpm_db_t *db)
}
/** Unregister all package databases. */
-int SYMEXPORT alpm_db_unregister_all(alpm_handle_t *handle)
+int SYMEXPORT alpm_unregister_all_syncdbs(alpm_handle_t *handle)
{
alpm_list_t *i;
alpm_db_t *db;
@@ -109,7 +107,7 @@ int SYMEXPORT alpm_db_unregister(alpm_db_t *db)
} else {
/* Warning : this function shouldn't be used to unregister all sync
* databases by walking through the list returned by
- * alpm_option_get_syncdbs, because the db is removed from that list here.
+ * alpm_get_syncdbs, because the db is removed from that list here.
*/
void *data;
handle->dbs_sync = alpm_list_remove(handle->dbs_sync,
@@ -263,7 +261,7 @@ alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(alpm_db_t *db)
}
/** Get a group entry from a package database. */
-alpm_group_t SYMEXPORT *alpm_db_readgroup(alpm_db_t *db, const char *name)
+alpm_group_t SYMEXPORT *alpm_db_get_group(alpm_db_t *db, const char *name)
{
ASSERT(db != NULL, return NULL);
db->handle->pm_errno = 0;
@@ -283,7 +281,7 @@ alpm_list_t SYMEXPORT *alpm_db_get_groupcache(alpm_db_t *db)
}
/** Searches a database. */
-alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles)
+alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t *needles)
{
ASSERT(db != NULL, return NULL);
db->handle->pm_errno = 0;
@@ -291,32 +289,6 @@ alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles)
return _alpm_db_search(db, needles);
}
-/** Set install reason for a package in db. */
-int SYMEXPORT alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg,
- alpm_pkgreason_t reason)
-{
- CHECK_HANDLE(handle, return -1);
- ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
- ASSERT(pkg->origin == PKG_FROM_LOCALDB,
- RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
- ASSERT(pkg->origin_data.db == handle->db_local,
- RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
-
- _alpm_log(handle, ALPM_LOG_DEBUG,
- "setting install reason %u for %s\n", reason, pkg->name);
- if(alpm_pkg_get_reason(pkg) == reason) {
- /* we are done */
- return 0;
- }
- /* set reason (in pkgcache) */
- pkg->reason = reason;
- /* write DESC */
- if(_alpm_local_db_write(handle->db_local, pkg, INFRQ_DESC)) {
- RET_ERR(handle, ALPM_ERR_DB_WRITE, -1);
- }
-
- return 0;
-}
/** @} */
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index 224bfbeb..94659b77 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -1,7 +1,7 @@
/*
* db.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org>
@@ -22,8 +22,6 @@
#ifndef _ALPM_DB_H
#define _ALPM_DB_H
-#include <time.h>
-
/* libarchive */
#include <archive.h>
#include <archive_entry.h>
diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c
index 6315a851..26ae5d5d 100644
--- a/lib/libalpm/delta.c
+++ b/lib/libalpm/delta.c
@@ -1,7 +1,7 @@
/*
* delta.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2007-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,8 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <string.h>
#include <stdint.h> /* intmax_t */
@@ -266,7 +264,8 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota
alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg)
{
ASSERT(pkg != NULL, return NULL);
- return find_unused(pkg->deltas, pkg->filename, pkg->size * MAX_DELTA_RATIO);
+ return find_unused(pkg->deltas, pkg->filename,
+ pkg->size * pkg->handle->deltaratio);
}
/** @} */
@@ -275,51 +274,54 @@ alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg)
* This function assumes that the string is in the correct format.
* This format is as follows:
* $deltafile $deltamd5 $deltasize $oldfile $newfile
+ * @param handle the context handle
* @param line the string to parse
* @return A pointer to the new alpm_delta_t object
*/
-/* TODO this does not really belong here, but in a parsing lib */
-alpm_delta_t *_alpm_delta_parse(char *line)
+alpm_delta_t *_alpm_delta_parse(alpm_handle_t *handle, const char *line)
{
alpm_delta_t *delta;
- char *tmp = line, *tmp2;
- regex_t reg;
-
- regcomp(&reg,
- "^[^[:space:]]* [[:xdigit:]]{32} [[:digit:]]*"
- " [^[:space:]]* [^[:space:]]*$",
- REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
- if(regexec(&reg, line, 0, 0, 0) != 0) {
+ const int num_matches = 6;
+ size_t len;
+ regmatch_t pmatch[num_matches];
+ char filesize[32];
+
+ /* this is so we only have to compile the pattern once */
+ if(!handle->delta_regex_compiled) {
+ /* $deltafile $deltamd5 $deltasize $oldfile $newfile*/
+ regcomp(&handle->delta_regex,
+ "^([^[:space:]]+) ([[:xdigit:]]{32}) ([[:digit:]]+)"
+ " ([^[:space:]]+) ([^[:space:]]+)$",
+ REG_EXTENDED | REG_NEWLINE);
+ handle->delta_regex_compiled = 1;
+ }
+
+ if(regexec(&handle->delta_regex, line, num_matches, pmatch, 0) != 0) {
/* delta line is invalid, return NULL */
- regfree(&reg);
return NULL;
}
- regfree(&reg);
CALLOC(delta, 1, sizeof(alpm_delta_t), return NULL);
- tmp2 = tmp;
- tmp = strchr(tmp, ' ');
- *(tmp++) = '\0';
- STRDUP(delta->delta, tmp2, return NULL);
+ /* start at index 1 -- match 0 is the entire match */
+ len = pmatch[1].rm_eo - pmatch[1].rm_so;
+ STRNDUP(delta->delta, &line[pmatch[1].rm_so], len, return NULL);
- tmp2 = tmp;
- tmp = strchr(tmp, ' ');
- *(tmp++) = '\0';
- STRDUP(delta->delta_md5, tmp2, return NULL);
+ len = pmatch[2].rm_eo - pmatch[2].rm_so;
+ STRNDUP(delta->delta_md5, &line[pmatch[2].rm_so], len, return NULL);
- tmp2 = tmp;
- tmp = strchr(tmp, ' ');
- *(tmp++) = '\0';
- delta->delta_size = _alpm_strtoofft(tmp2);
+ len = pmatch[3].rm_eo - pmatch[3].rm_so;
+ if(len < sizeof(filesize)) {
+ strncpy(filesize, &line[pmatch[3].rm_so], len);
+ filesize[len] = '\0';
+ delta->delta_size = _alpm_strtoofft(filesize);
+ }
- tmp2 = tmp;
- tmp = strchr(tmp, ' ');
- *(tmp++) = '\0';
- STRDUP(delta->from, tmp2, return NULL);
+ len = pmatch[4].rm_eo - pmatch[4].rm_so;
+ STRNDUP(delta->from, &line[pmatch[4].rm_so], len, return NULL);
- tmp2 = tmp;
- STRDUP(delta->to, tmp2, return NULL);
+ len = pmatch[5].rm_eo - pmatch[5].rm_so;
+ STRNDUP(delta->to, &line[pmatch[5].rm_so], len, return NULL);
return delta;
}
diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h
index 05df4207..b1c89912 100644
--- a/lib/libalpm/delta.h
+++ b/lib/libalpm/delta.h
@@ -1,7 +1,7 @@
/*
* delta.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2007-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -20,21 +20,16 @@
#ifndef _ALPM_DELTA_H
#define _ALPM_DELTA_H
-#include "config.h" /* ensure off_t is correct length */
-
#include <sys/types.h> /* off_t */
#include "alpm.h"
-alpm_delta_t *_alpm_delta_parse(char *line);
+alpm_delta_t *_alpm_delta_parse(alpm_handle_t *handle, const char *line);
void _alpm_delta_free(alpm_delta_t *delta);
alpm_delta_t *_alpm_delta_dup(const alpm_delta_t *delta);
off_t _alpm_shortest_delta_path(alpm_handle_t *handle, alpm_list_t *deltas,
const char *to, alpm_list_t **path);
-/* max percent of package size to download deltas */
-#define MAX_DELTA_RATIO 0.7
-
#endif /* _ALPM_DELTA_H */
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index 0c0a054e..2a06bb04 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -1,7 +1,7 @@
/*
* deps.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
@@ -20,8 +20,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -41,6 +39,7 @@ void _alpm_dep_free(alpm_depend_t *dep)
{
FREE(dep->name);
FREE(dep->version);
+ FREE(dep->desc);
FREE(dep);
}
@@ -159,15 +158,17 @@ alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle,
else if(nextchild->state == -1) {
alpm_pkg_t *vertexpkg = vertex->data;
alpm_pkg_t *childpkg = nextchild->data;
- const char *message;
_alpm_log(handle, ALPM_LOG_WARNING, _("dependency cycle detected:\n"));
if(reverse) {
- message =_("%s will be removed after its %s dependency\n");
+ _alpm_log(handle, ALPM_LOG_WARNING,
+ _("%s will be removed after its %s dependency\n"),
+ vertexpkg->name, childpkg->name);
} else {
- message =_("%s will be installed before its %s dependency\n");
+ _alpm_log(handle, ALPM_LOG_WARNING,
+ _("%s will be installed before its %s dependency\n"),
+ vertexpkg->name, childpkg->name);
}
- _alpm_log(handle, ALPM_LOG_WARNING, message, vertexpkg->name, childpkg->name);
}
}
if(!found) {
@@ -204,8 +205,10 @@ alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle,
static int no_dep_version(alpm_handle_t *handle)
{
- int flags = alpm_trans_get_flags(handle);
- return flags != -1 && (flags & ALPM_TRANS_FLAG_NODEPVERSION);
+ if(!handle->trans) {
+ return 0;
+ }
+ return (handle->trans->flags & ALPM_TRANS_FLAG_NODEPVERSION);
}
static alpm_depend_t *filtered_depend(alpm_depend_t *dep, int nodepversion)
@@ -266,7 +269,7 @@ alpm_pkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstri
* @return an alpm_list_t* of alpm_depmissing_t pointers.
*/
alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle,
- alpm_list_t *pkglist, alpm_list_t *remove, alpm_list_t *upgrade,
+ alpm_list_t *pkglist, alpm_list_t *rem, alpm_list_t *upgrade,
int reversedeps)
{
alpm_list_t *i, *j;
@@ -278,7 +281,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle,
for(i = pkglist; i; i = i->next) {
alpm_pkg_t *pkg = i->data;
- if(_alpm_pkg_find(remove, pkg->name) || _alpm_pkg_find(upgrade, pkg->name)) {
+ if(_alpm_pkg_find(rem, pkg->name) || _alpm_pkg_find(upgrade, pkg->name)) {
modified = alpm_list_add(modified, pkg);
} else {
dblist = alpm_list_add(dblist, pkg);
@@ -395,7 +398,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep)
/* any version will satisfy the requirement */
satisfy = (provision->name_hash == dep->name_hash
&& strcmp(provision->name, dep->name) == 0);
- } else if (provision->mod == ALPM_DEP_MOD_EQ) {
+ } else if(provision->mod == ALPM_DEP_MOD_EQ) {
/* provision specifies a version, so try it out */
satisfy = (provision->name_hash == dep->name_hash
&& strcmp(provision->name, dep->name) == 0
@@ -409,7 +412,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep)
alpm_depend_t *_alpm_splitdep(const char *depstring)
{
alpm_depend_t *depend;
- const char *ptr, *version;
+ const char *ptr, *version, *desc;
size_t deplen;
if(depstring == NULL) {
@@ -417,7 +420,17 @@ alpm_depend_t *_alpm_splitdep(const char *depstring)
}
MALLOC(depend, sizeof(alpm_depend_t), return NULL);
- deplen = strlen(depstring);
+
+ /* Note the extra space in ": " to avoid matching the epoch */
+ if((desc = strstr(depstring, ": ")) != NULL) {
+ STRDUP(depend->desc, desc + 2, return NULL);
+ deplen = desc - depstring;
+ } else {
+ /* no description- point desc at NULL at end of string for later use */
+ depend->desc = NULL;
+ deplen = strlen(depstring);
+ desc = depstring + deplen;
+ }
/* Find a version comparator if one exists. If it does, set the type and
* increment the ptr accordingly so we can copy the right strings. */
@@ -442,21 +455,18 @@ alpm_depend_t *_alpm_splitdep(const char *depstring)
depend->mod = ALPM_DEP_MOD_EQ;
version = ptr + 1;
} else {
- /* no version specified, leave ptr NULL and set version to NULL */
+ /* no version specified, set ptr to end of string and version to NULL */
+ ptr = depstring + deplen;
depend->mod = ALPM_DEP_MOD_ANY;
depend->version = NULL;
version = NULL;
}
/* copy the right parts to the right places */
- if(ptr) {
- STRNDUP(depend->name, depstring, ptr - depstring, return NULL);
- } else {
- STRDUP(depend->name, depstring, return NULL);
- }
+ STRNDUP(depend->name, depstring, ptr - depstring, return NULL);
depend->name_hash = _alpm_hash_sdbm(depend->name);
if(version) {
- STRDUP(depend->version, version, return NULL);
+ STRNDUP(depend->version, version, desc - version, return NULL);
}
return depend;
@@ -468,8 +478,9 @@ alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep)
CALLOC(newdep, 1, sizeof(alpm_depend_t), return NULL);
STRDUP(newdep->name, dep->name, return NULL);
- newdep->name_hash = dep->name_hash;
STRDUP(newdep->version, dep->version, return NULL);
+ STRDUP(newdep->desc, dep->desc, return NULL);
+ newdep->name_hash = dep->name_hash;
newdep->mod = dep->mod;
return newdep;
@@ -639,14 +650,14 @@ static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep,
count = alpm_list_count(providers);
if(count >= 1) {
/* default to first provider if there is no QUESTION callback */
- int index = 0;
+ int idx = 0;
if(count > 1) {
/* if there is more than one provider, we ask the user */
QUESTION(handle, ALPM_QUESTION_SELECT_PROVIDER,
- providers, dep, NULL, &index);
+ providers, dep, NULL, &idx);
}
- if(index >= 0 && index < count) {
- alpm_list_t *nth = alpm_list_nth(providers, index);
+ if(idx >= 0 && idx < count) {
+ alpm_list_t *nth = alpm_list_nth(providers, idx);
alpm_pkg_t *pkg = nth->data;
alpm_list_free(providers);
return pkg;
@@ -711,7 +722,7 @@ alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle,
*/
int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,
alpm_pkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages,
- alpm_list_t *remove, alpm_list_t **data)
+ alpm_list_t *rem, alpm_list_t **data)
{
int ret = 0;
alpm_list_t *i, *j;
@@ -734,7 +745,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,
for(i = alpm_list_last(*packages); i; i = i->next) {
alpm_pkg_t *tpkg = i->data;
targ = alpm_list_add(NULL, tpkg);
- deps = alpm_checkdeps(handle, localpkgs, remove, targ, 0);
+ deps = alpm_checkdeps(handle, localpkgs, rem, targ, 0);
alpm_list_free(targ);
for(j = deps; j; j = j->next) {
@@ -792,7 +803,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,
*/
char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep)
{
- const char *name, *opr, *ver;
+ const char *name, *opr, *ver, *desc_delim, *desc;
char *str;
size_t len;
@@ -834,12 +845,21 @@ char SYMEXPORT *alpm_dep_compute_string(const alpm_depend_t *dep)
ver = "";
}
+ if(dep->desc) {
+ desc_delim = ": ";
+ desc = dep->desc;
+ } else {
+ desc_delim = "";
+ desc = "";
+ }
+
/* we can always compute len and print the string like this because opr
* and ver will be empty when ALPM_DEP_MOD_ANY is the depend type. the
* reassignments above also ensure we do not do a strlen(NULL). */
- len = strlen(name) + strlen(opr) + strlen(ver) + 1;
+ len = strlen(name) + strlen(opr) + strlen(ver)
+ + strlen(desc_delim) + strlen(desc) + 1;
MALLOC(str, len, return NULL);
- snprintf(str, len, "%s%s%s", name, opr, ver);
+ snprintf(str, len, "%s%s%s%s%s", name, opr, ver, desc_delim, desc);
return str;
}
diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h
index ce25bda6..c8e1bc3d 100644
--- a/lib/libalpm/deps.h
+++ b/lib/libalpm/deps.h
@@ -1,7 +1,7 @@
/*
* deps.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org>
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index 45908b22..2582c4c3 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -17,8 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdio.h>
#include <errno.h>
@@ -60,6 +58,37 @@ static int mount_point_cmp(const void *p1, const void *p2)
return -strcmp(mp1->mount_dir, mp2->mount_dir);
}
+static void mount_point_list_free(alpm_list_t *mount_points)
+{
+ alpm_list_t *i;
+
+ for(i = mount_points; i; i = i->next) {
+ alpm_mountpoint_t *data = i->data;
+ FREE(data->mount_dir);
+ }
+ FREELIST(mount_points);
+}
+
+static int mount_point_load_fsinfo(alpm_handle_t *handle, alpm_mountpoint_t *mountpoint)
+{
+#if defined(HAVE_GETMNTENT)
+ /* grab the filesystem usage */
+ if(statvfs(mountpoint->mount_dir, &(mountpoint->fsp)) != 0) {
+ _alpm_log(handle, ALPM_LOG_WARNING,
+ _("could not get filesystem information for %s: %s\n"),
+ mountpoint->mount_dir, strerror(errno));
+ mountpoint->fsinfo_loaded = MOUNT_FSINFO_FAIL;
+ return -1;
+ }
+
+ _alpm_log(handle, ALPM_LOG_DEBUG, "loading fsinfo for %s\n", mountpoint->mount_dir);
+ mountpoint->read_only = mountpoint->fsp.f_flag & ST_RDONLY;
+ mountpoint->fsinfo_loaded = MOUNT_FSINFO_LOADED;
+#endif
+
+ return 0;
+}
+
static alpm_list_t *mount_point_list(alpm_handle_t *handle)
{
alpm_list_t *mount_points = NULL, *ptr;
@@ -73,28 +102,15 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
fp = setmntent(MOUNTED, "r");
if(fp == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file: %s: %s\n"),
+ MOUNTED, strerror(errno));
return NULL;
}
while((mnt = getmntent(fp))) {
- struct statvfs fsp;
- if(!mnt) {
- _alpm_log(handle, ALPM_LOG_WARNING,
- _("could not get filesystem information\n"));
- continue;
- }
- if(statvfs(mnt->mnt_dir, &fsp) != 0) {
- _alpm_log(handle, ALPM_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(handle, ALPM_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));
- mp->read_only = fsp.f_flag & ST_RDONLY;
mount_points = alpm_list_add(mount_points, mp);
}
@@ -109,23 +125,15 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
fp = fopen("/etc/mnttab", "r");
if(fp == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"),
+ "/etc/mnttab", strerror(errno));
return NULL;
}
while((ret = getmntent(fp, &mnt)) == 0) {
- struct statvfs fsp;
- if(statvfs(mnt->mnt_mountp, &fsp) != 0) {
- _alpm_log(handle, ALPM_LOG_WARNING,
- _("could not get filesystem information for %s: %s\n"),
- mnt->mnt_mountp, strerror(errno));
- continue;
- }
-
CALLOC(mp, 1, sizeof(alpm_mountpoint_t), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
mp->mount_dir = strdup(mnt->mnt_mountp);
mp->mount_dir_len = strlen(mp->mount_dir);
- memcpy(&(mp->fsp), &fsp, sizeof(struct statvfs));
- mp->read_only = fsp.f_flag & ST_RDONLY;
mount_points = alpm_list_add(mount_points, mp);
}
@@ -144,6 +152,8 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
entries = getmntinfo(&fsp, MNT_NOWAIT);
if(entries < 0) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("could not get filesystem information\n"));
return NULL;
}
@@ -158,6 +168,9 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
mp->read_only = fsp->f_flags & MNT_RDONLY;
#endif
+ /* we don't support lazy loading on this platform */
+ mp->fsinfo_loaded = MOUNT_FSINFO_LOADED;
+
mount_points = alpm_list_add(mount_points, mp);
}
#endif
@@ -166,7 +179,7 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
mount_point_cmp);
for(ptr = mount_points; ptr != NULL; ptr = ptr->next) {
mp = ptr->data;
- _alpm_log(handle, ALPM_LOG_DEBUG, "mountpoint: %s\n", mp->mount_dir);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "discovered mountpoint: %s\n", mp->mount_dir);
}
return mount_points;
}
@@ -215,6 +228,7 @@ static int calculate_removed_size(alpm_handle_t *handle,
alpm_mountpoint_t *mp;
struct stat st;
char path[PATH_MAX];
+ blkcnt_t remove_size;
const char *filename = file->name;
snprintf(path, PATH_MAX, "%s%s", handle->root, filename);
@@ -233,9 +247,21 @@ static int calculate_removed_size(alpm_handle_t *handle,
continue;
}
+ /* don't check a mount that we know we can't stat */
+ if(mp && mp->fsinfo_loaded == MOUNT_FSINFO_FAIL) {
+ continue;
+ }
+
+ /* lazy load filesystem info */
+ if(mp->fsinfo_loaded == MOUNT_FSINFO_UNLOADED) {
+ if(mount_point_load_fsinfo(handle, mp) < 0) {
+ continue;
+ }
+ }
+
/* the addition of (divisor - 1) performs ceil() with integer division */
- mp->blocks_needed -=
- (st.st_size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ remove_size = (st.st_size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ mp->blocks_needed -= remove_size;
mp->used |= USED_REMOVE;
}
@@ -256,6 +282,7 @@ static int calculate_installed_size(alpm_handle_t *handle,
const alpm_file_t *file = filelist->files + i;
alpm_mountpoint_t *mp;
char path[PATH_MAX];
+ blkcnt_t install_size;
const char *filename = file->name;
/* libarchive reports these as zero size anyways */
@@ -279,15 +306,108 @@ static int calculate_installed_size(alpm_handle_t *handle,
continue;
}
+ /* don't check a mount that we know we can't stat */
+ if(mp && mp->fsinfo_loaded == MOUNT_FSINFO_FAIL) {
+ continue;
+ }
+
+ /* lazy load filesystem info */
+ if(mp->fsinfo_loaded == MOUNT_FSINFO_UNLOADED) {
+ if(mount_point_load_fsinfo(handle, mp) < 0) {
+ continue;
+ }
+ }
+
/* the addition of (divisor - 1) performs ceil() with integer division */
- mp->blocks_needed +=
- (file->size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ install_size = (file->size + mp->fsp.f_bsize - 1) / mp->fsp.f_bsize;
+ mp->blocks_needed += install_size;
mp->used |= USED_INSTALL;
}
return 0;
}
+static int check_mountpoint(alpm_handle_t *handle, alpm_mountpoint_t *mp)
+{
+ /* cushion is roughly min(5% capacity, 20MiB) */
+ fsblkcnt_t fivepc = (mp->fsp.f_blocks / 20) + 1;
+ fsblkcnt_t twentymb = (20 * 1024 * 1024 / mp->fsp.f_bsize) + 1;
+ fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb;
+ blkcnt_t needed = mp->max_blocks_needed + cushion;
+
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "partition %s, needed %jd, cushion %ju, free %ju\n",
+ mp->mount_dir, (intmax_t)mp->max_blocks_needed,
+ (uintmax_t)cushion, (uintmax_t)mp->fsp.f_bfree);
+ if(needed >= 0 && (fsblkcnt_t)needed > mp->fsp.f_bfree) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("Partition %s too full: %jd blocks needed, %jd blocks free\n"),
+ mp->mount_dir, (intmax_t)needed, (uintmax_t)mp->fsp.f_bfree);
+ return 1;
+ }
+ return 0;
+}
+
+int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir,
+ size_t num_files, off_t *file_sizes)
+{
+ alpm_list_t *mount_points;
+ alpm_mountpoint_t *cachedir_mp;
+ char resolved_cachedir[PATH_MAX];
+ size_t j;
+ int error = 0;
+
+ /* resolve the cachedir path to ensure we check the right mountpoint. We
+ * handle failures silently, and continue to use the possibly unresolved
+ * path. */
+ if(realpath(cachedir, resolved_cachedir) != NULL) {
+ cachedir = resolved_cachedir;
+ }
+
+ mount_points = mount_point_list(handle);
+ if(mount_points == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n"));
+ return -1;
+ }
+
+ cachedir_mp = match_mount_point(mount_points, cachedir);
+ if(cachedir_mp == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine cachedir mount point %s\n"),
+ cachedir);
+ error = 1;
+ goto finish;
+ }
+
+ if(cachedir_mp->fsinfo_loaded == MOUNT_FSINFO_UNLOADED) {
+ if(mount_point_load_fsinfo(handle, cachedir_mp)) {
+ error = 1;
+ goto finish;
+ }
+ }
+
+ /* there's no need to check for a R/O mounted filesystem here, as
+ * _alpm_filecache_setup will never give us a non-writable directory */
+
+ /* round up the size of each file to the nearest block and accumulate */
+ for(j = 0; j < num_files; j++) {
+ cachedir_mp->max_blocks_needed += (file_sizes[j] + cachedir_mp->fsp.f_bsize + 1) /
+ cachedir_mp->fsp.f_bsize;
+ }
+
+ if(check_mountpoint(handle, cachedir_mp)) {
+ error = 1;
+ }
+
+finish:
+ mount_point_list_free(mount_points);
+
+ if(error) {
+ RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1);
+ }
+
+ return 0;
+}
+
int _alpm_check_diskspace(alpm_handle_t *handle)
{
alpm_list_t *mount_points, *i;
@@ -356,32 +476,13 @@ int _alpm_check_diskspace(alpm_handle_t *handle)
_alpm_log(handle, ALPM_LOG_ERROR, _("Partition %s is mounted read only\n"),
data->mount_dir);
error = 1;
- } else if(data->used & USED_INSTALL) {
- /* cushion is roughly min(5% capacity, 20MiB) */
- fsblkcnt_t fivepc = (data->fsp.f_blocks / 20) + 1;
- fsblkcnt_t twentymb = (20 * 1024 * 1024 / data->fsp.f_bsize) + 1;
- fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb;
- blkcnt_t needed = data->max_blocks_needed + cushion;
-
- _alpm_log(handle, ALPM_LOG_DEBUG,
- "partition %s, needed %jd, cushion %ju, free %ju\n",
- data->mount_dir, (intmax_t)data->max_blocks_needed,
- (uintmax_t)cushion, (uintmax_t)data->fsp.f_bfree);
- if(needed >= 0 && (fsblkcnt_t)needed > data->fsp.f_bfree) {
- _alpm_log(handle, ALPM_LOG_ERROR,
- _("Partition %s too full: %jd blocks needed, %jd blocks free\n"),
- data->mount_dir, (intmax_t)needed, (uintmax_t)data->fsp.f_bfree);
- error = 1;
- }
+ } else if(data->used & USED_INSTALL && check_mountpoint(handle, data)) {
+ error = 1;
}
}
finish:
- for(i = mount_points; i; i = i->next) {
- alpm_mountpoint_t *data = i->data;
- FREE(data->mount_dir);
- }
- FREELIST(mount_points);
+ mount_point_list_free(mount_points);
if(error) {
RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1);
diff --git a/lib/libalpm/diskspace.h b/lib/libalpm/diskspace.h
index 5944bb17..591d9337 100644
--- a/lib/libalpm/diskspace.h
+++ b/lib/libalpm/diskspace.h
@@ -1,7 +1,7 @@
/*
* diskspace.h
*
- * Copyright (c) 2010-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2010-2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +37,12 @@ enum mount_used_level {
USED_INSTALL = (1 << 1),
};
+enum mount_fsinfo {
+ MOUNT_FSINFO_UNLOADED = 0,
+ MOUNT_FSINFO_LOADED,
+ MOUNT_FSINFO_FAIL,
+};
+
typedef struct __alpm_mountpoint_t {
/* mount point information */
char *mount_dir;
@@ -46,10 +52,13 @@ typedef struct __alpm_mountpoint_t {
blkcnt_t max_blocks_needed;
enum mount_used_level used;
int read_only;
+ enum mount_fsinfo fsinfo_loaded;
FSSTATSTYPE fsp;
} alpm_mountpoint_t;
int _alpm_check_diskspace(alpm_handle_t *handle);
+int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir,
+ size_t num_files, off_t *file_sizes);
#endif /* _ALPM_DISKSPACE_H */
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index c1f54f02..6aaff1d2 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -18,8 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
@@ -324,7 +322,7 @@ static void curl_set_handle_opts(struct dload_payload *payload,
}
}
-static void mask_signal(int signal, void (*handler)(int),
+static void mask_signal(int signum, void (*handler)(int),
struct sigaction *origaction)
{
struct sigaction newaction;
@@ -333,13 +331,13 @@ static void mask_signal(int signal, void (*handler)(int),
sigemptyset(&newaction.sa_mask);
newaction.sa_flags = 0;
- sigaction(signal, NULL, origaction);
- sigaction(signal, &newaction, NULL);
+ sigaction(signum, NULL, origaction);
+ sigaction(signum, &newaction, NULL);
}
-static void unmask_signal(int signal, struct sigaction *sa)
+static void unmask_signal(int signum, struct sigaction *sa)
{
- sigaction(signal, sa, NULL);
+ sigaction(signum, sa, NULL);
}
static FILE *create_tempfile(struct dload_payload *payload, const char *localpath)
@@ -357,9 +355,7 @@ static FILE *create_tempfile(struct dload_payload *payload, const char *localpat
fchmod(fd, ~(_getumask()) & 0666) ||
!(fp = fdopen(fd, payload->tempfile_openmode))) {
unlink(randpath);
- if(fd >= 0) {
- close(fd);
- }
+ CLOSE(fd);
_alpm_log(payload->handle, ALPM_LOG_ERROR,
_("failed to create temporary file for download\n"));
return NULL;
@@ -432,6 +428,10 @@ static int curl_download_internal(struct dload_payload *payload,
if(localf == NULL) {
localf = fopen(payload->tempfile_name, payload->tempfile_openmode);
if(localf == NULL) {
+ handle->pm_errno = ALPM_ERR_RETRIEVE;
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("could not open file %s: %s\n"),
+ payload->tempfile_name, strerror(errno));
goto cleanup;
}
}
@@ -623,18 +623,18 @@ int _alpm_download(struct dload_payload *payload, const char *localpath,
static char *filecache_find_url(alpm_handle_t *handle, const char *url)
{
- const char *basename = strrchr(url, '/');
+ const char *filebase = strrchr(url, '/');
- if(basename == NULL) {
+ if(filebase == NULL) {
return NULL;
}
- basename++;
- if(basename == '\0') {
+ filebase++;
+ if(filebase == '\0') {
return NULL;
}
- return _alpm_filecache_find(handle, basename);
+ return _alpm_filecache_find(handle, filebase);
}
/** Fetch a remote pkg. */
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index f5f2cd9c..e279d564 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -1,7 +1,7 @@
/*
* dload.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -23,8 +23,6 @@
#include "alpm_list.h"
#include "alpm.h"
-#include <time.h>
-
struct dload_payload {
alpm_handle_t *handle;
const char *tempfile_openmode;
@@ -40,6 +38,7 @@ struct dload_payload {
int allow_resume;
int errors_ok;
int unlink_on_fail;
+ alpm_list_t *servers;
#ifdef HAVE_LIBCURL
CURLcode curlerr; /* last error produced by curl */
#endif
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index b3f56819..86b4efb2 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -1,7 +1,7 @@
/*
* error.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,8 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#ifdef HAVE_LIBCURL
#include <curl/curl.h>
#endif
@@ -29,12 +27,12 @@
#include "alpm.h"
#include "handle.h"
-enum _alpm_errno_t SYMEXPORT alpm_errno(alpm_handle_t *handle)
+alpm_errno_t SYMEXPORT alpm_errno(alpm_handle_t *handle)
{
return handle->pm_errno;
}
-const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err)
+const char SYMEXPORT *alpm_strerror(alpm_errno_t err)
{
switch(err) {
/* System */
@@ -43,7 +41,7 @@ const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err)
case ALPM_ERR_SYSTEM:
return _("unexpected system error");
case ALPM_ERR_BADPERMS:
- return _("insufficient privileges");
+ return _("permission denied");
case ALPM_ERR_NOT_A_FILE:
return _("could not find or read file");
case ALPM_ERR_NOT_A_DIR:
diff --git a/lib/libalpm/filelist.c b/lib/libalpm/filelist.c
new file mode 100644
index 00000000..f6c0ed45
--- /dev/null
+++ b/lib/libalpm/filelist.c
@@ -0,0 +1,137 @@
+/*
+ * filelist.c
+ *
+ * Copyright (c) 2012 Pacman Development Team <pacman-dev@archlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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 <string.h>
+
+/* libalpm */
+#include "filelist.h"
+
+/* Returns the difference of the provided two lists of files.
+ * Pre-condition: both lists are sorted!
+ * When done, free the list but NOT the contained data.
+ */
+alpm_list_t *_alpm_filelist_difference(alpm_filelist_t *filesA,
+ alpm_filelist_t *filesB)
+{
+ alpm_list_t *ret = NULL;
+ size_t ctrA = 0, ctrB = 0;
+
+ while(ctrA < filesA->count && ctrB < filesB->count) {
+ alpm_file_t *fileA = filesA->files + ctrA;
+ alpm_file_t *fileB = filesB->files + ctrB;
+ const char *strA = fileA->name;
+ const char *strB = fileB->name;
+ /* skip directories, we don't care about them */
+ if(strA[strlen(strA)-1] == '/') {
+ ctrA++;
+ } else if(strB[strlen(strB)-1] == '/') {
+ ctrB++;
+ } else {
+ int cmp = strcmp(strA, strB);
+ if(cmp < 0) {
+ /* item only in filesA, qualifies as a difference */
+ ret = alpm_list_add(ret, fileA);
+ ctrA++;
+ } else if(cmp > 0) {
+ ctrB++;
+ } else {
+ ctrA++;
+ ctrB++;
+ }
+ }
+ }
+
+ /* ensure we have completely emptied pA */
+ while(ctrA < filesA->count) {
+ alpm_file_t *fileA = filesA->files + ctrA;
+ const char *strA = fileA->name;
+ /* skip directories */
+ if(strA[strlen(strA)-1] != '/') {
+ ret = alpm_list_add(ret, fileA);
+ }
+ ctrA++;
+ }
+
+ return ret;
+}
+
+/* Returns the intersection of the provided two lists of files.
+ * Pre-condition: both lists are sorted!
+ * When done, free the list but NOT the contained data.
+ */
+alpm_list_t *_alpm_filelist_intersection(alpm_filelist_t *filesA,
+ alpm_filelist_t *filesB)
+{
+ alpm_list_t *ret = NULL;
+ size_t ctrA = 0, ctrB = 0;
+
+ while(ctrA < filesA->count && ctrB < filesB->count) {
+ alpm_file_t *fileA = filesA->files + ctrA;
+ alpm_file_t *fileB = filesB->files + ctrB;
+ const char *strA = fileA->name;
+ const char *strB = fileB->name;
+ /* skip directories, we don't care about them */
+ if(strA[strlen(strA)-1] == '/') {
+ ctrA++;
+ } else if(strB[strlen(strB)-1] == '/') {
+ ctrB++;
+ } else {
+ int cmp = strcmp(strA, strB);
+ if(cmp < 0) {
+ ctrA++;
+ } else if(cmp > 0) {
+ ctrB++;
+ } else {
+ /* item in both, qualifies as an intersect */
+ ret = alpm_list_add(ret, fileA);
+ ctrA++;
+ ctrB++;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/* Helper function for comparing files list entries
+ */
+int _alpm_files_cmp(const void *f1, const void *f2)
+{
+ const alpm_file_t *file1 = f1;
+ const alpm_file_t *file2 = f2;
+ return strcmp(file1->name, file2->name);
+}
+
+
+alpm_file_t *alpm_filelist_contains(alpm_filelist_t *filelist,
+ const char *path)
+{
+ alpm_file_t key;
+
+ if(!filelist) {
+ return NULL;
+ }
+
+ key.name = (char *)path;
+
+ return bsearch(&key, filelist->files, filelist->count,
+ sizeof(alpm_file_t), _alpm_files_cmp);
+}
+
+/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/filelist.h b/lib/libalpm/filelist.h
new file mode 100644
index 00000000..2d5cbc03
--- /dev/null
+++ b/lib/libalpm/filelist.h
@@ -0,0 +1,35 @@
+/*
+ * filelist.h
+ *
+ * Copyright (c) 2012 Pacman Development Team <pacman-dev@archlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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_FILELIST_H
+#define _ALPM_FILELIST_H
+
+#include "alpm.h"
+
+
+alpm_list_t *_alpm_filelist_difference(alpm_filelist_t *filesA,
+ alpm_filelist_t *filesB);
+
+alpm_list_t *_alpm_filelist_intersection(alpm_filelist_t *filesA,
+ alpm_filelist_t *filesB);
+
+int _alpm_files_cmp(const void *f1, const void *f2);
+
+#endif /* _ALPM_FILELIST_H */
+
+/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/graph.c b/lib/libalpm/graph.c
index 3a7f24b8..69be9e30 100644
--- a/lib/libalpm/graph.c
+++ b/lib/libalpm/graph.c
@@ -1,7 +1,7 @@
/*
* graph.c - helpful graph structure and setup/teardown methods
*
- * Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2007-2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,8 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include "graph.h"
#include "util.h"
#include "log.h"
diff --git a/lib/libalpm/graph.h b/lib/libalpm/graph.h
index d4d134b5..463b2cd8 100644
--- a/lib/libalpm/graph.h
+++ b/lib/libalpm/graph.h
@@ -1,7 +1,7 @@
/*
* graph.h - helpful graph structure and setup/teardown methods
*
- * Copyright (c) 2007-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2007-2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,8 +19,6 @@
#ifndef _ALPM_GRAPH_H
#define _ALPM_GRAPH_H
-#include "config.h" /* ensure off_t is correct length */
-
#include <sys/types.h> /* off_t */
#include "alpm_list.h"
diff --git a/lib/libalpm/group.c b/lib/libalpm/group.c
index 47458df2..7c3d64f7 100644
--- a/lib/libalpm/group.c
+++ b/lib/libalpm/group.c
@@ -1,7 +1,7 @@
/*
* group.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,8 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <string.h>
@@ -32,7 +30,7 @@
alpm_group_t *_alpm_group_new(const char *name)
{
- alpm_group_t* grp;
+ alpm_group_t *grp;
CALLOC(grp, 1, sizeof(alpm_group_t), return NULL);
STRDUP(grp->name, name, free(grp); return NULL);
diff --git a/lib/libalpm/group.h b/lib/libalpm/group.h
index 078c9af7..1f776ebf 100644
--- a/lib/libalpm/group.h
+++ b/lib/libalpm/group.h
@@ -1,7 +1,7 @@
/*
* group.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 7402be50..816162bd 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -1,7 +1,7 @@
/*
* handle.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
@@ -20,8 +20,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -36,6 +34,7 @@
#include "alpm_list.h"
#include "util.h"
#include "log.h"
+#include "delta.h"
#include "trans.h"
#include "alpm.h"
@@ -44,6 +43,7 @@ alpm_handle_t *_alpm_handle_new(void)
alpm_handle_t *handle;
CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL);
+ handle->deltaratio = 0.0;
return handle;
}
@@ -69,6 +69,8 @@ void _alpm_handle_free(alpm_handle_t *handle)
curl_easy_cleanup(handle->curl);
#endif
+ regfree(&handle->delta_regex);
+
/* free memory */
_alpm_trans_free(handle->trans);
FREE(handle->root);
@@ -251,10 +253,10 @@ const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle)
return handle->arch;
}
-int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle)
+double SYMEXPORT alpm_option_get_deltaratio(alpm_handle_t *handle)
{
CHECK_HANDLE(handle, return -1);
- return handle->usedelta;
+ return handle->deltaratio;
}
int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)
@@ -263,18 +265,6 @@ int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)
return handle->checkspace;
}
-alpm_db_t SYMEXPORT *alpm_option_get_localdb(alpm_handle_t *handle)
-{
- CHECK_HANDLE(handle, return NULL);
- return handle->db_local;
-}
-
-alpm_list_t SYMEXPORT *alpm_option_get_syncdbs(alpm_handle_t *handle)
-{
- CHECK_HANDLE(handle, return NULL);
- return handle->dbs_sync;
-}
-
int SYMEXPORT alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb)
{
CHECK_HANDLE(handle, return -1);
@@ -339,11 +329,11 @@ static char *canonicalize_path(const char *path) {
return new_path;
}
-enum _alpm_errno_t _alpm_set_directory_option(const char *value,
+alpm_errno_t _alpm_set_directory_option(const char *value,
char **storage, int must_exist)
{
struct stat st;
- char *real = NULL;
+ char real[PATH_MAX];
const char *path;
path = value;
@@ -354,9 +344,7 @@ enum _alpm_errno_t _alpm_set_directory_option(const char *value,
if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
return ALPM_ERR_NOT_A_DIR;
}
- CALLOC(real, PATH_MAX, sizeof(char), return ALPM_ERR_MEMORY);
if(!realpath(path, real)) {
- free(real);
return ALPM_ERR_NOT_A_DIR;
}
path = real;
@@ -369,7 +357,6 @@ enum _alpm_errno_t _alpm_set_directory_option(const char *value,
if(!*storage) {
return ALPM_ERR_MEMORY;
}
- free(real);
return 0;
}
@@ -596,10 +583,13 @@ int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)
return 0;
}
-int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta)
+int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio)
{
CHECK_HANDLE(handle, return -1);
- handle->usedelta = usedelta;
+ if(ratio < 0.0 || ratio > 2.0) {
+ RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+ }
+ handle->deltaratio = ratio;
return 0;
}
@@ -630,4 +620,16 @@ alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle
return handle->siglevel;
}
+alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle)
+{
+ CHECK_HANDLE(handle, return NULL);
+ return handle->db_local;
+}
+
+alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle)
+{
+ CHECK_HANDLE(handle, return NULL);
+ return handle->dbs_sync;
+}
+
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 8477dcae..c0ad6686 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -1,7 +1,7 @@
/*
* handle.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <sys/types.h>
+#include <regex.h>
#include "alpm_list.h"
#include "alpm.h"
@@ -86,14 +87,18 @@ struct __alpm_handle_t {
alpm_list_t *ignoregroup; /* List of groups to ignore */
/* options */
- int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
char *arch; /* Architecture of packages we should allow */
- int usedelta; /* Download deltas if possible */
+ double deltaratio; /* Download deltas if possible; a ratio value */
+ int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */
int checkspace; /* Check disk space before installing */
alpm_siglevel_t siglevel; /* Default signature verification level */
/* error code */
- enum _alpm_errno_t pm_errno;
+ alpm_errno_t pm_errno;
+
+ /* for delta parsing efficiency */
+ int delta_regex_compiled;
+ regex_t delta_regex;
};
alpm_handle_t *_alpm_handle_new(void);
@@ -102,7 +107,7 @@ void _alpm_handle_free(alpm_handle_t *handle);
int _alpm_handle_lock(alpm_handle_t *handle);
int _alpm_handle_unlock(alpm_handle_t *handle);
-enum _alpm_errno_t _alpm_set_directory_option(const char *value,
+alpm_errno_t _alpm_set_directory_option(const char *value,
char **storage, int must_exist);
#endif /* _ALPM_HANDLE_H */
diff --git a/lib/libalpm/libalpm.pc.in b/lib/libalpm/libalpm.pc.in
new file mode 100644
index 00000000..fe4e2583
--- /dev/null
+++ b/lib/libalpm/libalpm.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libalpm
+Description: Arch Linux package management library
+URL: http://www.archlinux.org/pacman/
+Version: @VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lalpm
+Libs.private: @LIBS@ @LIBARCHIVE_LIBS@ @LIBSSL_LIBS@ @LIBCURL_LIBS@ @GPGME_LIBS@
diff --git a/lib/libalpm/log.c b/lib/libalpm/log.c
index 692ff79c..8486716e 100644
--- a/lib/libalpm/log.c
+++ b/lib/libalpm/log.c
@@ -1,7 +1,7 @@
/*
* log.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,8 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
diff --git a/lib/libalpm/log.h b/lib/libalpm/log.h
index a43290d8..22c3d065 100644
--- a/lib/libalpm/log.h
+++ b/lib/libalpm/log.h
@@ -1,7 +1,7 @@
/*
* log.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/lib/libalpm/md5.c b/lib/libalpm/md5.c
index b4391a61..0d5ed9e0 100644
--- a/lib/libalpm/md5.c
+++ b/lib/libalpm/md5.c
@@ -33,33 +33,34 @@
* GPL. This is from version 1.0.0 of the library, and has been modified
* as following, which may be helpful for future updates:
* * remove "polarssl/config.h" include
- * * change include from "polarssl/sha2.h" to "sha2.h"
+ * * change include from "polarssl/md5.h" to "md5.h"
* * removal of HMAC code
* * removal of SELF_TEST code
- * * removal of ipad and opad from the md5_context struct in sha2.h
+ * * removal of ipad and opad from the md5_context struct in md5.h
* * increase the size of buffer for performance reasons
- * * various static changes
+ * * change 'unsigned long' to uint32_t
*/
#include <stdio.h>
+#include <stdint.h>
#include "md5.h"
/*
* 32-bit integer manipulation macros (little endian)
*/
-#ifndef GET_ULONG_LE
-#define GET_ULONG_LE(n,b,i) \
+#ifndef GET_U32_LE
+#define GET_U32_LE(n,b,i) \
{ \
- (n) = ( (unsigned long) (b)[(i) ] ) \
- | ( (unsigned long) (b)[(i) + 1] << 8 ) \
- | ( (unsigned long) (b)[(i) + 2] << 16 ) \
- | ( (unsigned long) (b)[(i) + 3] << 24 ); \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
-#ifndef PUT_ULONG_LE
-#define PUT_ULONG_LE(n,b,i) \
+#ifndef PUT_U32_LE
+#define PUT_U32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
@@ -84,24 +85,24 @@ static void md5_starts( md5_context *ctx )
static void md5_process( md5_context *ctx, const unsigned char data[64] )
{
- unsigned long X[16], A, B, C, D;
-
- GET_ULONG_LE( X[ 0], data, 0 );
- GET_ULONG_LE( X[ 1], data, 4 );
- GET_ULONG_LE( X[ 2], data, 8 );
- GET_ULONG_LE( X[ 3], data, 12 );
- GET_ULONG_LE( X[ 4], data, 16 );
- GET_ULONG_LE( X[ 5], data, 20 );
- GET_ULONG_LE( X[ 6], data, 24 );
- GET_ULONG_LE( X[ 7], data, 28 );
- GET_ULONG_LE( X[ 8], data, 32 );
- GET_ULONG_LE( X[ 9], data, 36 );
- GET_ULONG_LE( X[10], data, 40 );
- GET_ULONG_LE( X[11], data, 44 );
- GET_ULONG_LE( X[12], data, 48 );
- GET_ULONG_LE( X[13], data, 52 );
- GET_ULONG_LE( X[14], data, 56 );
- GET_ULONG_LE( X[15], data, 60 );
+ uint32_t X[16], A, B, C, D;
+
+ GET_U32_LE( X[ 0], data, 0 );
+ GET_U32_LE( X[ 1], data, 4 );
+ GET_U32_LE( X[ 2], data, 8 );
+ GET_U32_LE( X[ 3], data, 12 );
+ GET_U32_LE( X[ 4], data, 16 );
+ GET_U32_LE( X[ 5], data, 20 );
+ GET_U32_LE( X[ 6], data, 24 );
+ GET_U32_LE( X[ 7], data, 28 );
+ GET_U32_LE( X[ 8], data, 32 );
+ GET_U32_LE( X[ 9], data, 36 );
+ GET_U32_LE( X[10], data, 40 );
+ GET_U32_LE( X[11], data, 44 );
+ GET_U32_LE( X[12], data, 48 );
+ GET_U32_LE( X[13], data, 52 );
+ GET_U32_LE( X[14], data, 56 );
+ GET_U32_LE( X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
@@ -211,7 +212,7 @@ static void md5_process( md5_context *ctx, const unsigned char data[64] )
static void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
- unsigned long left;
+ uint32_t left;
if( ilen <= 0 )
return;
@@ -219,10 +220,10 @@ static void md5_update( md5_context *ctx, const unsigned char *input, size_t ile
left = ctx->total[0] & 0x3F;
fill = 64 - left;
- ctx->total[0] += (unsigned long) ilen;
+ ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
- if( ctx->total[0] < (unsigned long) ilen )
+ if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
@@ -262,16 +263,16 @@ static const unsigned char md5_padding[64] =
*/
static void md5_finish( md5_context *ctx, unsigned char output[16] )
{
- unsigned long last, padn;
- unsigned long high, low;
+ uint32_t last, padn;
+ uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
- PUT_ULONG_LE( low, msglen, 0 );
- PUT_ULONG_LE( high, msglen, 4 );
+ PUT_U32_LE( low, msglen, 0 );
+ PUT_U32_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
@@ -279,10 +280,10 @@ static void md5_finish( md5_context *ctx, unsigned char output[16] )
md5_update( ctx, (unsigned char *) md5_padding, padn );
md5_update( ctx, msglen, 8 );
- PUT_ULONG_LE( ctx->state[0], output, 0 );
- PUT_ULONG_LE( ctx->state[1], output, 4 );
- PUT_ULONG_LE( ctx->state[2], output, 8 );
- PUT_ULONG_LE( ctx->state[3], output, 12 );
+ PUT_U32_LE( ctx->state[0], output, 0 );
+ PUT_U32_LE( ctx->state[1], output, 4 );
+ PUT_U32_LE( ctx->state[2], output, 8 );
+ PUT_U32_LE( ctx->state[3], output, 12 );
}
/*
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index a5ff238f..a4c3309e 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -1,7 +1,7 @@
/*
* package.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005, 2006 by Christian Hamar <krics@linuxforum.hu>
@@ -21,8 +21,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
@@ -48,7 +46,7 @@ int SYMEXPORT alpm_pkg_free(alpm_pkg_t *pkg)
ASSERT(pkg != NULL, return -1);
/* Only free packages loaded in user space */
- if(pkg->origin == PKG_FROM_FILE) {
+ if(pkg->origin == ALPM_PKG_FROM_FILE) {
_alpm_pkg_free(pkg);
}
@@ -64,12 +62,12 @@ int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg)
ASSERT(pkg != NULL, return -1);
pkg->handle->pm_errno = 0;
/* We only inspect packages from sync repositories */
- ASSERT(pkg->origin == PKG_FROM_SYNCDB,
+ ASSERT(pkg->origin == ALPM_PKG_FROM_SYNCDB,
RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
fpath = _alpm_filecache_find(pkg->handle, pkg->filename);
- retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_CSUM_MD5);
+ retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_PKG_VALIDATION_MD5SUM);
if(retval == 0) {
return 0;
@@ -87,12 +85,13 @@ int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg)
* populated package structures. */
static const char *_pkg_get_desc(alpm_pkg_t *pkg) { return pkg->desc; }
static const char *_pkg_get_url(alpm_pkg_t *pkg) { return pkg->url; }
-static time_t _pkg_get_builddate(alpm_pkg_t *pkg) { return pkg->builddate; }
-static time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; }
+static alpm_time_t _pkg_get_builddate(alpm_pkg_t *pkg) { return pkg->builddate; }
+static alpm_time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; }
static const char *_pkg_get_packager(alpm_pkg_t *pkg) { return pkg->packager; }
static const char *_pkg_get_arch(alpm_pkg_t *pkg) { return pkg->arch; }
static off_t _pkg_get_isize(alpm_pkg_t *pkg) { return pkg->isize; }
-static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; }
+static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; }
+static alpm_pkgvalidation_t _pkg_get_validation(alpm_pkg_t *pkg) { return pkg->validation; }
static int _pkg_has_scriptlet(alpm_pkg_t *pkg) { return pkg->scriptlet; }
static alpm_list_t *_pkg_get_licenses(alpm_pkg_t *pkg) { return pkg->licenses; }
@@ -136,6 +135,7 @@ struct pkg_operations default_pkg_ops = {
.get_arch = _pkg_get_arch,
.get_isize = _pkg_get_isize,
.get_reason = _pkg_get_reason,
+ .get_validation = _pkg_get_validation,
.has_scriptlet = _pkg_has_scriptlet,
.get_licenses = _pkg_get_licenses,
@@ -200,14 +200,14 @@ const char SYMEXPORT *alpm_pkg_get_url(alpm_pkg_t *pkg)
return pkg->ops->get_url(pkg);
}
-time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg)
+alpm_time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg)
{
ASSERT(pkg != NULL, return -1);
pkg->handle->pm_errno = 0;
return pkg->ops->get_builddate(pkg);
}
-time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg)
+alpm_time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg)
{
ASSERT(pkg != NULL, return -1);
pkg->handle->pm_errno = 0;
@@ -270,6 +270,13 @@ alpm_pkgreason_t SYMEXPORT alpm_pkg_get_reason(alpm_pkg_t *pkg)
return pkg->ops->get_reason(pkg);
}
+alpm_pkgvalidation_t SYMEXPORT alpm_pkg_get_validation(alpm_pkg_t *pkg)
+{
+ ASSERT(pkg != NULL, return -1);
+ pkg->handle->pm_errno = 0;
+ return pkg->ops->get_validation(pkg);
+}
+
alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(alpm_pkg_t *pkg)
{
ASSERT(pkg != NULL, return NULL);
@@ -344,7 +351,7 @@ alpm_db_t SYMEXPORT *alpm_pkg_get_db(alpm_pkg_t *pkg)
{
/* Sanity checks */
ASSERT(pkg != NULL, return NULL);
- ASSERT(pkg->origin != PKG_FROM_FILE, return NULL);
+ ASSERT(pkg->origin != ALPM_PKG_FROM_FILE, return NULL);
pkg->handle->pm_errno = 0;
return pkg->origin_data.db;
@@ -411,7 +418,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg)
ASSERT(pkg != NULL, return NULL);
pkg->handle->pm_errno = 0;
- if(pkg->origin == PKG_FROM_FILE) {
+ if(pkg->origin == ALPM_PKG_FROM_FILE) {
/* The sane option; search locally for things that require this. */
find_requiredby(pkg, pkg->handle->db_local, &reqs);
} else {
@@ -443,24 +450,24 @@ alpm_file_t *_alpm_file_copy(alpm_file_t *dest,
return dest;
}
-/* Helper function for comparing files list entries
- */
-int _alpm_files_cmp(const void *f1, const void *f2)
-{
- const alpm_file_t *file1 = f1;
- const alpm_file_t *file2 = f2;
- return strcmp(file1->name, file2->name);
-}
-
alpm_pkg_t *_alpm_pkg_new(void)
{
- alpm_pkg_t* pkg;
+ alpm_pkg_t *pkg;
CALLOC(pkg, 1, sizeof(alpm_pkg_t), return NULL);
return pkg;
}
+static alpm_list_t *list_depdup(alpm_list_t *old)
+{
+ alpm_list_t *i, *new = NULL;
+ for(i = old; i; i = i->next) {
+ new = alpm_list_add(new, _alpm_dep_dup(i->data));
+ }
+ return new;
+}
+
/**
* Duplicate a package data struct.
* @param pkg the package to duplicate
@@ -509,10 +516,19 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)
newpkg->reason = pkg->reason;
newpkg->licenses = alpm_list_strdup(pkg->licenses);
- for(i = pkg->replaces; i; i = i->next) {
- newpkg->replaces = alpm_list_add(newpkg->replaces, _alpm_dep_dup(i->data));
- }
+ newpkg->replaces = list_depdup(pkg->replaces);
newpkg->groups = alpm_list_strdup(pkg->groups);
+ for(i = pkg->backup; i; i = i->next) {
+ newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data));
+ }
+ newpkg->depends = list_depdup(pkg->depends);
+ newpkg->optdepends = list_depdup(pkg->optdepends);
+ newpkg->conflicts = list_depdup(pkg->conflicts);
+ newpkg->provides = list_depdup(pkg->provides);
+ for(i = pkg->deltas; i; i = i->next) {
+ newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data));
+ }
+
if(pkg->files.count) {
size_t filenum;
size_t len = sizeof(alpm_file_t) * pkg->files.count;
@@ -525,27 +541,11 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)
}
newpkg->files.count = pkg->files.count;
}
- for(i = pkg->backup; i; i = i->next) {
- newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data));
- }
- for(i = pkg->depends; i; i = i->next) {
- newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data));
- }
- newpkg->optdepends = alpm_list_strdup(pkg->optdepends);
- for(i = pkg->conflicts; i; i = i->next) {
- newpkg->conflicts = alpm_list_add(newpkg->conflicts, _alpm_dep_dup(i->data));
- }
- for(i = pkg->provides; i; i = i->next) {
- newpkg->provides = alpm_list_add(newpkg->provides, _alpm_dep_dup(i->data));
- }
- for(i = pkg->deltas; i; i = i->next) {
- newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data));
- }
/* internal */
newpkg->infolevel = pkg->infolevel;
newpkg->origin = pkg->origin;
- if(newpkg->origin == PKG_FROM_FILE) {
+ if(newpkg->origin == ALPM_PKG_FROM_FILE) {
newpkg->origin_data.file = strdup(pkg->origin_data.file);
} else {
newpkg->origin_data.db = pkg->origin_data.db;
@@ -561,6 +561,12 @@ cleanup:
RET_ERR(pkg->handle, ALPM_ERR_MEMORY, -1);
}
+static void free_deplist(alpm_list_t *deps)
+{
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_dep_free);
+ alpm_list_free(deps);
+}
+
void _alpm_pkg_free(alpm_pkg_t *pkg)
{
if(pkg == NULL) {
@@ -579,8 +585,7 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)
FREE(pkg->arch);
FREELIST(pkg->licenses);
- alpm_list_free_inner(pkg->replaces, (alpm_list_fn_free)_alpm_dep_free);
- alpm_list_free(pkg->replaces);
+ free_deplist(pkg->replaces);
FREELIST(pkg->groups);
if(pkg->files.count) {
size_t i;
@@ -591,27 +596,24 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)
}
alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free);
alpm_list_free(pkg->backup);
- alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free);
- alpm_list_free(pkg->depends);
- FREELIST(pkg->optdepends);
- alpm_list_free_inner(pkg->conflicts, (alpm_list_fn_free)_alpm_dep_free);
- alpm_list_free(pkg->conflicts);
- alpm_list_free_inner(pkg->provides, (alpm_list_fn_free)_alpm_dep_free);
- alpm_list_free(pkg->provides);
+ free_deplist(pkg->depends);
+ free_deplist(pkg->optdepends);
+ free_deplist(pkg->conflicts);
+ free_deplist(pkg->provides);
alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free);
alpm_list_free(pkg->deltas);
alpm_list_free(pkg->delta_path);
alpm_list_free(pkg->removes);
- if(pkg->origin == PKG_FROM_FILE) {
+ if(pkg->origin == ALPM_PKG_FROM_FILE) {
FREE(pkg->origin_data.file);
}
FREE(pkg);
}
/* This function should be used when removing a target from upgrade/sync target list
- * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed.
- * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed,
+ * Case 1: If pkg is a loaded package file (ALPM_PKG_FROM_FILE), it will be freed.
+ * Case 2: If pkg is a pkgcache entry (ALPM_PKG_FROM_CACHE), it won't be freed,
* only the transaction specific fields of pkg will be freed.
*/
void _alpm_pkg_free_trans(alpm_pkg_t *pkg)
@@ -620,7 +622,7 @@ void _alpm_pkg_free_trans(alpm_pkg_t *pkg)
return;
}
- if(pkg->origin == PKG_FROM_FILE) {
+ if(pkg->origin == ALPM_PKG_FROM_FILE) {
_alpm_pkg_free(pkg);
return;
}
@@ -690,14 +692,14 @@ int _alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg)
alpm_list_t *groups = NULL;
/* first see if the package is ignored */
- if(alpm_list_find_str(handle->ignorepkg, pkg->name)) {
+ if(alpm_list_find(handle->ignorepkg, pkg->name, _alpm_fnmatch)) {
return 1;
}
/* next see if the package is in a group that is ignored */
- for(groups = handle->ignoregroup; groups; groups = groups->next) {
+ for(groups = alpm_pkg_get_groups(pkg); groups; groups = groups->next) {
char *grp = groups->data;
- if(alpm_list_find_str(alpm_pkg_get_groups(pkg), grp)) {
+ if(alpm_list_find(handle->ignoregroup, grp, _alpm_fnmatch)) {
return 1;
}
}
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index eff7d898..313fe9dd 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -1,7 +1,7 @@
/*
* package.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org>
@@ -24,10 +24,7 @@
#ifndef _ALPM_PACKAGE_H
#define _ALPM_PACKAGE_H
-#include "config.h" /* ensure off_t is correct length */
-
#include <sys/types.h> /* off_t */
-#include <time.h> /* time_t */
#include "alpm.h"
#include "backup.h"
@@ -44,12 +41,13 @@
struct pkg_operations {
const char *(*get_desc) (alpm_pkg_t *);
const char *(*get_url) (alpm_pkg_t *);
- time_t (*get_builddate) (alpm_pkg_t *);
- time_t (*get_installdate) (alpm_pkg_t *);
+ alpm_time_t (*get_builddate) (alpm_pkg_t *);
+ alpm_time_t (*get_installdate) (alpm_pkg_t *);
const char *(*get_packager) (alpm_pkg_t *);
const char *(*get_arch) (alpm_pkg_t *);
off_t (*get_isize) (alpm_pkg_t *);
alpm_pkgreason_t (*get_reason) (alpm_pkg_t *);
+ alpm_pkgvalidation_t (*get_validation) (alpm_pkg_t *);
int (*has_scriptlet) (alpm_pkg_t *);
alpm_list_t *(*get_licenses) (alpm_pkg_t *);
@@ -89,8 +87,8 @@ struct __alpm_pkg_t {
char *base64_sig;
char *arch;
- time_t builddate;
- time_t installdate;
+ alpm_time_t builddate;
+ alpm_time_t installdate;
off_t size;
off_t isize;
@@ -99,6 +97,7 @@ struct __alpm_pkg_t {
int scriptlet;
alpm_pkgreason_t reason;
+ alpm_pkgvalidation_t validation;
alpm_dbinfrq_t infolevel;
alpm_pkgfrom_t origin;
/* origin == PKG_FROM_FILE, use pkg->origin_data.file
@@ -127,16 +126,15 @@ struct __alpm_pkg_t {
};
alpm_file_t *_alpm_file_copy(alpm_file_t *dest, const alpm_file_t *src);
-int _alpm_files_cmp(const void *f1, const void *f2);
-alpm_pkg_t* _alpm_pkg_new(void);
+alpm_pkg_t *_alpm_pkg_new(void);
int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr);
void _alpm_pkg_free(alpm_pkg_t *pkg);
void _alpm_pkg_free_trans(alpm_pkg_t *pkg);
int _alpm_pkg_validate_internal(alpm_handle_t *handle,
const char *pkgfile, alpm_pkg_t *syncpkg, alpm_siglevel_t level,
- alpm_siglist_t **sigdata);
+ alpm_siglist_t **sigdata, alpm_pkgvalidation_t *validation);
alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
const char *pkgfile, int full);
diff --git a/lib/libalpm/pkghash.c b/lib/libalpm/pkghash.c
index 963ba25e..7b388004 100644
--- a/lib/libalpm/pkghash.c
+++ b/lib/libalpm/pkghash.c
@@ -1,7 +1,7 @@
/*
* pkghash.c
*
- * Copyright (c) 2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2011-2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,42 +26,51 @@
*
* The maximum table size is the last prime under 1,000,000. That is
* more than an order of magnitude greater than the number of packages
- * in any Linux distribution.
+ * in any Linux distribution, and well under UINT_MAX.
*/
-static const size_t prime_list[] =
+static const unsigned int prime_list[] =
{
- 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul, 37ul, 41ul, 43ul, 47ul,
- 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul, 83ul, 89ul, 97ul, 103ul,
- 109ul, 113ul, 127ul, 137ul, 139ul, 149ul, 157ul, 167ul, 179ul, 193ul,
- 199ul, 211ul, 227ul, 241ul, 257ul, 277ul, 293ul, 313ul, 337ul, 359ul,
- 383ul, 409ul, 439ul, 467ul, 503ul, 541ul, 577ul, 619ul, 661ul, 709ul,
- 761ul, 823ul, 887ul, 953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul,
- 1493ul, 1613ul, 1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul,
- 2753ul, 2971ul, 3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul,
- 5087ul, 5503ul, 5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul,
- 9497ul, 10273ul, 11113ul, 12011ul, 12983ul, 14033ul, 15173ul,
- 16411ul, 17749ul, 19183ul, 20753ul, 22447ul, 24281ul, 26267ul,
- 28411ul, 30727ul, 33223ul, 35933ul, 38873ul, 42043ul, 45481ul,
- 49201ul, 53201ul, 57557ul, 62233ul, 67307ul, 72817ul, 78779ul,
- 85229ul, 92203ul, 99733ul, 107897ul, 116731ul, 126271ul, 136607ul,
- 147793ul, 159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul,
- 256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul, 410857ul,
- 444487ul, 480881ul, 520241ul, 562841ul, 608903ul, 658753ul, 712697ul,
- 771049ul, 834181ul, 902483ul, 976369ul
+ 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u, 41u, 43u, 47u,
+ 53u, 59u, 61u, 67u, 71u, 73u, 79u, 83u, 89u, 97u, 103u,
+ 109u, 113u, 127u, 137u, 139u, 149u, 157u, 167u, 179u, 193u,
+ 199u, 211u, 227u, 241u, 257u, 277u, 293u, 313u, 337u, 359u,
+ 383u, 409u, 439u, 467u, 503u, 541u, 577u, 619u, 661u, 709u,
+ 761u, 823u, 887u, 953u, 1031u, 1109u, 1193u, 1289u, 1381u,
+ 1493u, 1613u, 1741u, 1879u, 2029u, 2179u, 2357u, 2549u,
+ 2753u, 2971u, 3209u, 3469u, 3739u, 4027u, 4349u, 4703u,
+ 5087u, 5503u, 5953u, 6427u, 6949u, 7517u, 8123u, 8783u,
+ 9497u, 10273u, 11113u, 12011u, 12983u, 14033u, 15173u,
+ 16411u, 17749u, 19183u, 20753u, 22447u, 24281u, 26267u,
+ 28411u, 30727u, 33223u, 35933u, 38873u, 42043u, 45481u,
+ 49201u, 53201u, 57557u, 62233u, 67307u, 72817u, 78779u,
+ 85229u, 92203u, 99733u, 107897u, 116731u, 126271u, 136607u,
+ 147793u, 159871u, 172933u, 187091u, 202409u, 218971u, 236897u,
+ 256279u, 277261u, 299951u, 324503u, 351061u, 379787u, 410857u,
+ 444487u, 480881u, 520241u, 562841u, 608903u, 658753u, 712697u,
+ 771049u, 834181u, 902483u, 976369u
};
-/* Allocate a hash table with at least "size" buckets */
-alpm_pkghash_t *_alpm_pkghash_create(size_t size)
+/* How far forward do we look when linear probing for a spot? */
+static const unsigned int stride = 1;
+/* What is the maximum load percentage of our hash table? */
+static const double max_hash_load = 0.68;
+/* Initial load percentage given a certain size */
+static const double initial_hash_load = 0.58;
+
+/* Allocate a hash table with space for at least "size" elements */
+alpm_pkghash_t *_alpm_pkghash_create(unsigned int size)
{
alpm_pkghash_t *hash = NULL;
- size_t i, loopsize;
+ unsigned int i, loopsize;
CALLOC(hash, 1, sizeof(alpm_pkghash_t), return NULL);
+ size = size / initial_hash_load + 1;
loopsize = sizeof(prime_list) / sizeof(*prime_list);
for(i = 0; i < loopsize; i++) {
if(prime_list[i] > size) {
hash->buckets = prime_list[i];
+ hash->limit = hash->buckets * max_hash_load;
break;
}
}
@@ -78,15 +87,19 @@ alpm_pkghash_t *_alpm_pkghash_create(size_t size)
return hash;
}
-static size_t get_hash_position(unsigned long name_hash, alpm_pkghash_t *hash)
+static unsigned int get_hash_position(unsigned long name_hash,
+ alpm_pkghash_t *hash)
{
- size_t position;
+ unsigned int position;
position = name_hash % hash->buckets;
/* collision resolution using open addressing with linear probing */
while(hash->hash_table[position] != NULL) {
- position = (position + 1) % hash->buckets;
+ position += stride;
+ while(position >= hash->buckets) {
+ position -= hash->buckets;
+ }
}
return position;
@@ -96,7 +109,7 @@ static size_t get_hash_position(unsigned long name_hash, alpm_pkghash_t *hash)
static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash)
{
alpm_pkghash_t *newhash;
- size_t newsize, position, i;
+ unsigned int newsize, i;
/* Hash tables will need resized in two cases:
* - adding packages to the local database
@@ -129,8 +142,7 @@ static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash)
for(i = 0; i < oldhash->buckets; i++) {
if(oldhash->hash_table[i] != NULL) {
alpm_pkg_t *package = oldhash->hash_table[i]->data;
-
- position = get_hash_position(package->name_hash, newhash);
+ unsigned int position = get_hash_position(package->name_hash, newhash);
newhash->hash_table[position] = oldhash->hash_table[i];
oldhash->hash_table[i] = NULL;
@@ -144,16 +156,17 @@ static alpm_pkghash_t *rehash(alpm_pkghash_t *oldhash)
return newhash;
}
-static alpm_pkghash_t *pkghash_add_pkg(alpm_pkghash_t *hash, alpm_pkg_t *pkg, int sorted)
+static alpm_pkghash_t *pkghash_add_pkg(alpm_pkghash_t *hash, alpm_pkg_t *pkg,
+ int sorted)
{
alpm_list_t *ptr;
- size_t position;
+ unsigned int position;
if(pkg == NULL || hash == NULL) {
return hash;
}
- if((hash->entries + 1) / MAX_HASH_LOAD > hash->buckets) {
+ if(hash->entries >= hash->limit) {
hash = rehash(hash);
}
@@ -189,7 +202,8 @@ alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg)
return pkghash_add_pkg(hash, pkg, 1);
}
-static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end)
+static unsigned int move_one_entry(alpm_pkghash_t *hash,
+ unsigned int start, unsigned int end)
{
/* Iterate backwards from 'end' to 'start', seeing if any of the items
* would hash to 'start'. If we find one, we move it there and break. If
@@ -201,7 +215,7 @@ static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end)
while(end != start) {
alpm_list_t *i = hash->hash_table[end];
alpm_pkg_t *info = i->data;
- size_t new_position = get_hash_position(info->name_hash, hash);
+ unsigned int new_position = get_hash_position(info->name_hash, hash);
if(new_position == start) {
hash->hash_table[start] = i;
@@ -212,7 +226,7 @@ static size_t move_one_entry(alpm_pkghash_t *hash, size_t start, size_t end)
/* the odd math ensures we are always positive, e.g.
* e.g. (0 - 1) % 47 == -1
* e.g. (47 + 0 - 1) % 47 == 46 */
- end = (hash->buckets + end - 1) % hash->buckets;
+ end = (hash->buckets + end - stride) % hash->buckets;
}
return end;
}
@@ -230,7 +244,7 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,
alpm_pkg_t **data)
{
alpm_list_t *i;
- size_t position;
+ unsigned int position;
if(data) {
*data = NULL;
@@ -246,7 +260,7 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,
if(info->name_hash == pkg->name_hash &&
strcmp(info->name, pkg->name) == 0) {
- size_t stop, prev;
+ unsigned int stop, prev;
/* remove from list and hash */
hash->list = alpm_list_remove_item(hash->list, i);
@@ -260,11 +274,17 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,
/* Potentially move entries following removed entry to keep open
* addressing collision resolution working. We start by finding the
* next null bucket to know how far we have to look. */
- stop = (position + 1) % hash->buckets;
+ stop = position + stride;
+ while(stop >= hash->buckets) {
+ stop -= hash->buckets;
+ }
while(hash->hash_table[stop] != NULL && stop != position) {
- stop = (stop + 1) % hash->buckets;
+ stop += stride;
+ while(stop >= hash->buckets) {
+ stop -= hash->buckets;
+ }
}
- stop = (hash->buckets + stop - 1) % hash->buckets;
+ stop = (hash->buckets + stop - stride) % hash->buckets;
/* We now search backwards from stop to position. If we find an
* item that now hashes to position, we will move it, and then try
@@ -277,7 +297,10 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,
return hash;
}
- position = (position + 1) % hash->buckets;
+ position += stride;
+ while(position >= hash->buckets) {
+ position -= hash->buckets;
+ }
}
return hash;
@@ -285,8 +308,8 @@ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg,
void _alpm_pkghash_free(alpm_pkghash_t *hash)
{
- size_t i;
if(hash != NULL) {
+ unsigned int i;
for(i = 0; i < hash->buckets; i++) {
free(hash->hash_table[i]);
}
@@ -299,7 +322,7 @@ alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name)
{
alpm_list_t *lp;
unsigned long name_hash;
- size_t position;
+ unsigned int position;
if(name == NULL || hash == NULL) {
return NULL;
@@ -316,7 +339,10 @@ alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name)
return info;
}
- position = (position + 1) % hash->buckets;
+ position += stride;
+ while(position >= hash->buckets) {
+ position -= hash->buckets;
+ }
}
return NULL;
diff --git a/lib/libalpm/pkghash.h b/lib/libalpm/pkghash.h
index edd500e9..a2c39c7f 100644
--- a/lib/libalpm/pkghash.h
+++ b/lib/libalpm/pkghash.h
@@ -1,7 +1,7 @@
/*
* pkghash.h
*
- * Copyright (c) 2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2011-2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,17 +35,19 @@
struct __alpm_pkghash_t {
/** data held by the hash table */
alpm_list_t **hash_table;
- /** number of buckets in hash table */
- size_t buckets;
- /** number of entries in hash table */
- size_t entries;
/** head node of the hash table data in normal list format */
alpm_list_t *list;
+ /** number of buckets in hash table */
+ unsigned int buckets;
+ /** number of entries in hash table */
+ unsigned int entries;
+ /** max number of entries before a resize is needed */
+ unsigned int limit;
};
typedef struct __alpm_pkghash_t alpm_pkghash_t;
-alpm_pkghash_t *_alpm_pkghash_create(size_t size);
+alpm_pkghash_t *_alpm_pkghash_create(unsigned int size);
alpm_pkghash_t *_alpm_pkghash_add(alpm_pkghash_t *hash, alpm_pkg_t *pkg);
alpm_pkghash_t *_alpm_pkghash_add_sorted(alpm_pkghash_t *hash, alpm_pkg_t *pkg);
@@ -55,6 +57,4 @@ void _alpm_pkghash_free(alpm_pkghash_t *hash);
alpm_pkg_t *_alpm_pkghash_find(alpm_pkghash_t *hash, const char *name);
-#define MAX_HASH_LOAD 0.7
-
#endif /* _ALPM_PKGHASH_H */
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index cc9e289d..4c549926 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -22,8 +22,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <errno.h>
#include <string.h>
@@ -43,8 +41,16 @@
#include "db.h"
#include "deps.h"
#include "handle.h"
-#include "conflict.h"
+#include "filelist.h"
+/**
+ * @brief 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
+ */
int SYMEXPORT alpm_remove_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg)
{
const char *pkgname;
@@ -75,6 +81,14 @@ int SYMEXPORT alpm_remove_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg)
return 0;
}
+/**
+ * @brief Add dependencies to the removal transaction for cascading.
+ *
+ * @param handle the context handle
+ * @param lp list of missing dependencies caused by the removal transaction
+ *
+ * @return 0 on success, -1 on error
+ */
static int remove_prepare_cascade(alpm_handle_t *handle, alpm_list_t *lp)
{
alpm_trans_t *trans = handle->trans;
@@ -107,6 +121,12 @@ static int remove_prepare_cascade(alpm_handle_t *handle, alpm_list_t *lp)
return 0;
}
+/**
+ * @brief Remove needed packages from the removal transaction.
+ *
+ * @param handle the context handle
+ * @param lp list of missing dependencies caused by the removal transaction
+ */
static void remove_prepare_keep_needed(alpm_handle_t *handle, alpm_list_t *lp)
{
alpm_trans_t *trans = handle->trans;
@@ -137,12 +157,16 @@ static void remove_prepare_keep_needed(alpm_handle_t *handle, alpm_list_t *lp)
}
}
-/** Transaction preparation for remove actions.
+/**
+ * @brief Transaction preparation for remove actions.
+ *
* This functions takes a pointer to a alpm_list_t which will be
* filled with a list of alpm_depmissing_t* objects representing
* the packages blocking the transaction.
+ *
* @param handle the context handle
* @param data a pointer to an alpm_list_t* to fill
+ *
* @return 0 on success, -1 on error
*/
int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data)
@@ -211,12 +235,21 @@ int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data)
return 0;
}
+/**
+ * @brief Check if alpm can delete a file.
+ *
+ * @param handle the context handle
+ * @param file file to be removed
+ * @param skip_remove list of files that will not be removed
+ *
+ * @return 1 if the file can be deleted, 0 if it cannot be deleted
+ */
static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file,
alpm_list_t *skip_remove)
{
char filepath[PATH_MAX];
- if(alpm_list_find_str(skip_remove, file->name)) {
+ if(alpm_list_find(skip_remove, file->name, _alpm_fnmatch)) {
/* return success because we will never actually remove this file */
return 1;
}
@@ -237,10 +270,26 @@ static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file,
return 1;
}
-/* Helper function for iterating through a package's file and deleting them
- * Used by _alpm_remove_commit. */
-static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
- const alpm_file_t *fileobj, alpm_list_t *skip_remove, int nosave)
+/**
+ * @brief Unlink a package file, backing it up if necessary.
+ *
+ * @note Helper function for iterating through a package's file and deleting
+ * them.
+ * @note Used by _alpm_remove_commit.
+ *
+ * @param handle the context handle
+ * @param oldpkg the package being removed
+ * @param newpkg the package replacing \a oldpkg
+ * @param fileobj file to remove
+ * @param skip_remove list of files that shouldn't be removed
+ * @param nosave whether files should be backed up
+ *
+ * @return 0 on success, -1 if there was an error unlinking the file, 1 if the
+ * file was skipped or did not exist
+ */
+static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *oldpkg,
+ alpm_pkg_t *newpkg, const alpm_file_t *fileobj, alpm_list_t *skip_remove,
+ int nosave)
{
struct stat buf;
char file[PATH_MAX];
@@ -250,7 +299,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
/* check the remove skip list before removing the file.
* see the big comment block in db_find_fileconflicts() for an
* explanation. */
- if(alpm_list_find_str(skip_remove, fileobj->name)) {
+ if(alpm_list_find(skip_remove, fileobj->name, _alpm_fnmatch)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"%s is in skip_remove, skipping removal\n", file);
return 1;
@@ -274,6 +323,10 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
} else if(files < 0) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"keeping directory %s (could not count files)\n", file);
+ } else if(newpkg && alpm_filelist_contains(alpm_pkg_get_files(newpkg),
+ fileobj->name)) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "keeping directory %s (in new package)\n", file);
} else {
/* one last check- does any other package own this file? */
alpm_list_t *local, *local_pkgs;
@@ -285,11 +338,12 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
/* we duplicated the package when we put it in the removal list, so we
* so we can't use direct pointer comparison here. */
- if(_alpm_pkg_cmp(info, local_pkg) == 0) {
+ if(oldpkg->name_hash == local_pkg->name_hash
+ && strcmp(oldpkg->name, local_pkg->name) == 0) {
continue;
}
filelist = alpm_pkg_get_files(local_pkg);
- if(_alpm_filelist_contains(filelist, fileobj->name)) {
+ if(alpm_filelist_contains(filelist, fileobj->name)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"keeping directory %s (owned by %s)\n", file, local_pkg->name);
found = 1;
@@ -308,7 +362,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
}
} else {
/* if the file needs backup and has been modified, back it up to .pacsave */
- alpm_backup_t *backup = _alpm_needbackup(fileobj->name, info);
+ alpm_backup_t *backup = _alpm_needbackup(fileobj->name, oldpkg);
if(backup) {
if(nosave) {
_alpm_log(handle, ALPM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file);
@@ -350,38 +404,28 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
return 0;
}
-int _alpm_remove_single_package(alpm_handle_t *handle,
+/**
+ * @brief Remove a package's files, optionally skipping its replacement's
+ * files.
+ *
+ * @param handle the context handle
+ * @param oldpkg package to remove
+ * @param newpkg package to replace \a oldpkg (optional)
+ * @param targ_count current index within the transaction (1-based)
+ * @param pkg_count the number of packages affected by the transaction
+ *
+ * @return 0 on success, -1 if alpm lacks permission to delete some of the
+ * files, >0 the number of files alpm was unable to delete
+ */
+static int remove_package_files(alpm_handle_t *handle,
alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg,
size_t targ_count, size_t pkg_count)
{
alpm_list_t *skip_remove;
- size_t filenum = 0, position = 0;
- const char *pkgname = oldpkg->name;
- const char *pkgver = oldpkg->version;
alpm_filelist_t *filelist;
size_t i;
-
- if(newpkg) {
- _alpm_log(handle, ALPM_LOG_DEBUG, "removing old package first (%s-%s)\n",
- pkgname, pkgver);
- } else {
- EVENT(handle, ALPM_EVENT_REMOVE_START, oldpkg, NULL);
- _alpm_log(handle, ALPM_LOG_DEBUG, "removing package %s-%s\n",
- pkgname, pkgver);
-
- /* run the pre-remove scriptlet if it exists */
- if(alpm_pkg_has_scriptlet(oldpkg) &&
- !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) {
- char *scriptlet = _alpm_local_db_pkgpath(handle->db_local,
- oldpkg, "install");
- _alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0);
- free(scriptlet);
- }
- }
-
- if(handle->trans->flags & ALPM_TRANS_FLAG_DBONLY) {
- goto db;
- }
+ int err = 0;
+ int nosave = handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE;
if(newpkg) {
alpm_filelist_t *newfiles;
@@ -396,7 +440,7 @@ int _alpm_remove_single_package(alpm_handle_t *handle,
for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) {
const alpm_backup_t *backup = b->data;
/* safety check (fix the upgrade026 pactest) */
- if(!_alpm_filelist_contains(newfiles, backup->name)) {
+ if(!alpm_filelist_contains(newfiles, backup->name)) {
continue;
}
_alpm_log(handle, ALPM_LOG_DEBUG, "adding %s to the skip_remove array\n",
@@ -412,54 +456,100 @@ int _alpm_remove_single_package(alpm_handle_t *handle,
alpm_file_t *file = filelist->files + i;
if(!can_remove_file(handle, file, skip_remove)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
- "not removing package '%s', can't remove all files\n", pkgname);
+ "not removing package '%s', can't remove all files\n",
+ oldpkg->name);
+ FREELIST(skip_remove);
RET_ERR(handle, ALPM_ERR_PKG_CANT_REMOVE, -1);
}
- filenum++;
}
- _alpm_log(handle, ALPM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "removing %zd files\n", filelist->count);
if(!newpkg) {
/* init progress bar, but only on true remove transactions */
- PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, 0,
+ PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name, 0,
pkg_count, targ_count);
}
/* iterate through the list backwards, unlinking files */
for(i = filelist->count; i > 0; i--) {
alpm_file_t *file = filelist->files + i - 1;
- int percent;
- /* TODO: check return code and handle accordingly */
- unlink_file(handle, oldpkg, file, skip_remove,
- handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE);
+ if(unlink_file(handle, oldpkg, newpkg, file, skip_remove, nosave) < 0) {
+ err++;
+ }
if(!newpkg) {
/* update progress bar after each file */
- percent = (position * 100) / filenum;
- PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname,
+ int percent = ((filelist->count - i) * 100) / filelist->count;
+ PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name,
percent, pkg_count, targ_count);
}
- position++;
}
FREELIST(skip_remove);
if(!newpkg) {
/* set progress to 100% after we finish unlinking files */
- PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, pkgname, 100,
+ PROGRESS(handle, ALPM_PROGRESS_REMOVE_START, oldpkg->name, 100,
pkg_count, targ_count);
+ }
+
+ return err;
+}
+
+/**
+ * @brief Remove a package from the filesystem.
+ *
+ * @param handle the context handle
+ * @param oldpkg package to remove
+ * @param newpkg package to replace \a oldpkg (optional)
+ * @param targ_count current index within the transaction (1-based)
+ * @param pkg_count the number of packages affected by the transaction
+ *
+ * @return 0
+ */
+int _alpm_remove_single_package(alpm_handle_t *handle,
+ alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg,
+ size_t targ_count, size_t pkg_count)
+{
+ const char *pkgname = oldpkg->name;
+ const char *pkgver = oldpkg->version;
- /* run the post-remove script if it exists */
+ if(newpkg) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "removing old package first (%s-%s)\n",
+ pkgname, pkgver);
+ } else {
+ EVENT(handle, ALPM_EVENT_REMOVE_START, oldpkg, NULL);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "removing package %s-%s\n",
+ pkgname, pkgver);
+
+ /* run the pre-remove scriptlet if it exists */
if(alpm_pkg_has_scriptlet(oldpkg) &&
!(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) {
char *scriptlet = _alpm_local_db_pkgpath(handle->db_local,
oldpkg, "install");
- _alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0);
+ _alpm_runscriptlet(handle, scriptlet, "pre_remove", pkgver, NULL, 0);
free(scriptlet);
}
}
-db:
+ if(!(handle->trans->flags & ALPM_TRANS_FLAG_DBONLY)) {
+ /* TODO check returned errors if any */
+ remove_package_files(handle, oldpkg, newpkg, targ_count, pkg_count);
+ }
+
+ /* run the post-remove script if it exists */
+ if(!newpkg && alpm_pkg_has_scriptlet(oldpkg) &&
+ !(handle->trans->flags & ALPM_TRANS_FLAG_NOSCRIPTLET)) {
+ char *scriptlet = _alpm_local_db_pkgpath(handle->db_local,
+ oldpkg, "install");
+ _alpm_runscriptlet(handle, scriptlet, "post_remove", pkgver, NULL, 0);
+ free(scriptlet);
+ }
+
+ if(!newpkg) {
+ EVENT(handle, ALPM_EVENT_REMOVE_DONE, oldpkg, NULL);
+ }
+
/* remove the package from the database */
_alpm_log(handle, ALPM_LOG_DEBUG, "removing database entry '%s'\n", pkgname);
if(_alpm_local_db_remove(handle->db_local, oldpkg) == -1) {
@@ -472,14 +562,18 @@ db:
pkgname);
}
- if(!newpkg) {
- /* TODO: awesome! we're passing invalid pointers. */
- EVENT(handle, ALPM_EVENT_REMOVE_DONE, oldpkg, NULL);
- }
-
+ /* TODO: useful return values */
return 0;
}
+/**
+ * @brief Remove packages in the current transaction.
+ *
+ * @param handle the context handle
+ * @param run_ldconfig whether to run ld_config after removing the packages
+ *
+ * @return 0 on success, -1 if errors occurred while removing files
+ */
int _alpm_remove_packages(alpm_handle_t *handle, int run_ldconfig)
{
alpm_list_t *targ;
diff --git a/lib/libalpm/remove.h b/lib/libalpm/remove.h
index 251e4548..203eccb4 100644
--- a/lib/libalpm/remove.h
+++ b/lib/libalpm/remove.h
@@ -1,7 +1,7 @@
/*
* remove.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
diff --git a/lib/libalpm/sha2.c b/lib/libalpm/sha2.c
index 3632c131..366dc650 100644
--- a/lib/libalpm/sha2.c
+++ b/lib/libalpm/sha2.c
@@ -38,28 +38,29 @@
* * removal of SELF_TEST code
* * removal of ipad and opad from the sha2_context struct in sha2.h
* * increase the size of buffer for performance reasons
- * * various static changes
+ * * change 'unsigned long' to uint32_t
*/
#include <stdio.h>
+#include <stdint.h>
#include "sha2.h"
/*
* 32-bit integer manipulation macros (big endian)
*/
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i) \
+#ifndef GET_U32_BE
+#define GET_U32_BE(n,b,i) \
{ \
- (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
- | ( (unsigned long) (b)[(i) + 1] << 16 ) \
- | ( (unsigned long) (b)[(i) + 2] << 8 ) \
- | ( (unsigned long) (b)[(i) + 3] ); \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i) \
+#ifndef PUT_U32_BE
+#define PUT_U32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
@@ -106,25 +107,25 @@ static void sha2_starts( sha2_context *ctx, int is224 )
static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
{
- unsigned long temp1, temp2, W[64];
- unsigned long A, B, C, D, E, F, G, H;
-
- GET_ULONG_BE( W[ 0], data, 0 );
- GET_ULONG_BE( W[ 1], data, 4 );
- GET_ULONG_BE( W[ 2], data, 8 );
- GET_ULONG_BE( W[ 3], data, 12 );
- GET_ULONG_BE( W[ 4], data, 16 );
- GET_ULONG_BE( W[ 5], data, 20 );
- GET_ULONG_BE( W[ 6], data, 24 );
- GET_ULONG_BE( W[ 7], data, 28 );
- GET_ULONG_BE( W[ 8], data, 32 );
- GET_ULONG_BE( W[ 9], data, 36 );
- GET_ULONG_BE( W[10], data, 40 );
- GET_ULONG_BE( W[11], data, 44 );
- GET_ULONG_BE( W[12], data, 48 );
- GET_ULONG_BE( W[13], data, 52 );
- GET_ULONG_BE( W[14], data, 56 );
- GET_ULONG_BE( W[15], data, 60 );
+ uint32_t temp1, temp2, W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_U32_BE( W[ 0], data, 0 );
+ GET_U32_BE( W[ 1], data, 4 );
+ GET_U32_BE( W[ 2], data, 8 );
+ GET_U32_BE( W[ 3], data, 12 );
+ GET_U32_BE( W[ 4], data, 16 );
+ GET_U32_BE( W[ 5], data, 20 );
+ GET_U32_BE( W[ 6], data, 24 );
+ GET_U32_BE( W[ 7], data, 28 );
+ GET_U32_BE( W[ 8], data, 32 );
+ GET_U32_BE( W[ 9], data, 36 );
+ GET_U32_BE( W[10], data, 40 );
+ GET_U32_BE( W[11], data, 44 );
+ GET_U32_BE( W[12], data, 48 );
+ GET_U32_BE( W[13], data, 52 );
+ GET_U32_BE( W[14], data, 56 );
+ GET_U32_BE( W[15], data, 60 );
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
@@ -241,7 +242,7 @@ static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
static void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
- unsigned long left;
+ uint32_t left;
if( ilen <= 0 )
return;
@@ -249,10 +250,10 @@ static void sha2_update( sha2_context *ctx, const unsigned char *input, size_t i
left = ctx->total[0] & 0x3F;
fill = 64 - left;
- ctx->total[0] += (unsigned long) ilen;
+ ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
- if( ctx->total[0] < (unsigned long) ilen )
+ if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
@@ -292,16 +293,16 @@ static const unsigned char sha2_padding[64] =
*/
static void sha2_finish( sha2_context *ctx, unsigned char output[32] )
{
- unsigned long last, padn;
- unsigned long high, low;
+ uint32_t last, padn;
+ uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
- PUT_ULONG_BE( high, msglen, 0 );
- PUT_ULONG_BE( low, msglen, 4 );
+ PUT_U32_BE( high, msglen, 0 );
+ PUT_U32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
@@ -309,16 +310,16 @@ static void sha2_finish( sha2_context *ctx, unsigned char output[32] )
sha2_update( ctx, (unsigned char *) sha2_padding, padn );
sha2_update( ctx, msglen, 8 );
- PUT_ULONG_BE( ctx->state[0], output, 0 );
- PUT_ULONG_BE( ctx->state[1], output, 4 );
- PUT_ULONG_BE( ctx->state[2], output, 8 );
- PUT_ULONG_BE( ctx->state[3], output, 12 );
- PUT_ULONG_BE( ctx->state[4], output, 16 );
- PUT_ULONG_BE( ctx->state[5], output, 20 );
- PUT_ULONG_BE( ctx->state[6], output, 24 );
+ PUT_U32_BE( ctx->state[0], output, 0 );
+ PUT_U32_BE( ctx->state[1], output, 4 );
+ PUT_U32_BE( ctx->state[2], output, 8 );
+ PUT_U32_BE( ctx->state[3], output, 12 );
+ PUT_U32_BE( ctx->state[4], output, 16 );
+ PUT_U32_BE( ctx->state[5], output, 20 );
+ PUT_U32_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
- PUT_ULONG_BE( ctx->state[7], output, 28 );
+ PUT_U32_BE( ctx->state[7], output, 28 );
}
/*
diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c
index 7177d655..1e417164 100644
--- a/lib/libalpm/signing.c
+++ b/lib/libalpm/signing.c
@@ -17,8 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -292,11 +290,34 @@ static int key_search(alpm_handle_t *handle, const char *fpr,
pgpkey->email = key->uids->email;
pgpkey->created = key->subkeys->timestamp;
pgpkey->expires = key->subkeys->expires;
- gpgme_release(ctx);
- return 1;
+ pgpkey->length = key->subkeys->length;
+ pgpkey->revoked = key->subkeys->revoked;
+
+ switch (key->subkeys->pubkey_algo) {
+ case GPGME_PK_RSA:
+ case GPGME_PK_RSA_E:
+ case GPGME_PK_RSA_S:
+ pgpkey->pubkey_algo = 'R';
+ break;
+
+ case GPGME_PK_DSA:
+ pgpkey->pubkey_algo = 'D';
+ break;
+
+ case GPGME_PK_ELG_E:
+ case GPGME_PK_ELG:
+ case GPGME_PK_ECDSA:
+ case GPGME_PK_ECDH:
+ pgpkey->pubkey_algo = 'E';
+ break;
+ }
+
+ ret = 1;
error:
- _alpm_log(handle, ALPM_LOG_DEBUG, "gpg error: %s\n", gpgme_strerror(err));
+ if(ret != 1) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "gpg error: %s\n", gpgme_strerror(err));
+ }
free(full_fpr);
gpgme_release(ctx);
return ret;
@@ -418,8 +439,13 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
if(!base64_sig) {
sigpath = _alpm_sigpath(handle, path);
- /* this will just help debugging */
- _alpm_access(handle, NULL, sigpath, R_OK);
+ if(_alpm_access(handle, NULL, sigpath, R_OK) != 0
+ || (sigfile = fopen(sigpath, "rb")) == NULL) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n",
+ sigpath);
+ handle->pm_errno = ALPM_ERR_SIG_MISSING;
+ goto error;
+ }
}
/* does the file we are verifying exist? */
@@ -429,17 +455,6 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
goto error;
}
- /* does the sig file exist (if we didn't get the data directly)? */
- if(!base64_sig) {
- sigfile = fopen(sigpath, "rb");
- if(sigfile == NULL) {
- _alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n",
- sigpath);
- handle->pm_errno = ALPM_ERR_SIG_MISSING;
- goto error;
- }
- }
-
if(init_gpgme(handle)) {
/* pm_errno was set in gpgme_init() */
goto error;
diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h
index 315d6059..19ffef27 100644
--- a/lib/libalpm/signing.h
+++ b/lib/libalpm/signing.h
@@ -1,7 +1,7 @@
/*
* signing.h
*
- * Copyright (c) 2008-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2008-2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index e500d90f..ca6b507e 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -1,7 +1,7 @@
/*
* sync.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
@@ -21,8 +21,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <sys/types.h> /* off_t */
#include <stdlib.h>
#include <stdio.h>
@@ -251,7 +249,7 @@ alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs,
for(i = dbs; i; i = i->next) {
alpm_db_t *db = i->data;
- alpm_group_t *grp = alpm_db_readgroup(db, name);
+ alpm_group_t *grp = alpm_db_get_group(db, name);
if(!grp)
continue;
@@ -291,7 +289,7 @@ static int compute_download_size(alpm_pkg_t *newpkg)
alpm_handle_t *handle = newpkg->handle;
int ret = 0;
- if(newpkg->origin != PKG_FROM_SYNCDB) {
+ if(newpkg->origin != ALPM_PKG_FROM_SYNCDB) {
newpkg->infolevel |= INFRQ_DSIZE;
newpkg->download_size = 0;
return 0;
@@ -321,13 +319,13 @@ static int compute_download_size(alpm_pkg_t *newpkg)
/* tell the caller that we have a partial */
ret = 1;
- } else if(handle->usedelta) {
+ } else if(handle->deltaratio > 0.0) {
off_t dltsize;
dltsize = _alpm_shortest_delta_path(handle, newpkg->deltas,
newpkg->filename, &newpkg->delta_path);
- if(newpkg->delta_path && (dltsize < newpkg->size * MAX_DELTA_RATIO)) {
+ if(newpkg->delta_path && (dltsize < newpkg->size * handle->deltaratio)) {
_alpm_log(handle, ALPM_LOG_DEBUG, "using delta size\n");
size = dltsize;
} else {
@@ -368,7 +366,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
for(i = trans->add; i; i = i->next) {
alpm_pkg_t *spkg = i->data;
- from_sync += (spkg->origin == PKG_FROM_SYNCDB);
+ from_sync += (spkg->origin == ALPM_PKG_FROM_SYNCDB);
}
/* ensure all sync database are valid if we will be using them */
@@ -424,7 +422,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
see if they'd like to ignore them rather than failing the sync */
if(unresolvable != NULL) {
int remove_unresolvable = 0;
- enum _alpm_errno_t saved_err = handle->pm_errno;
+ alpm_errno_t saved_err = handle->pm_errno;
QUESTION(handle, ALPM_QUESTION_REMOVE_PKGS, unresolvable,
NULL, NULL, &remove_unresolvable);
if(remove_unresolvable) {
@@ -696,11 +694,11 @@ static int apply_deltas(alpm_handle_t *handle)
} else {
/* len = cachedir len + from len + '/' + null */
len = strlen(cachedir) + strlen(d->from) + 2;
- CALLOC(from, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1));
+ MALLOC(from, len, RET_ERR(handle, ALPM_ERR_MEMORY, 1));
snprintf(from, len, "%s/%s", cachedir, d->from);
}
len = strlen(cachedir) + strlen(d->to) + 2;
- CALLOC(to, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, 1));
+ MALLOC(to, len, RET_ERR(handle, ALPM_ERR_MEMORY, 1));
snprintf(to, len, "%s/%s", cachedir, d->to);
/* build the patch command */
@@ -758,7 +756,7 @@ static int apply_deltas(alpm_handle_t *handle)
* @return 1 if file was removed, 0 otherwise
*/
static int prompt_to_delete(alpm_handle_t *handle, const char *filepath,
- enum _alpm_errno_t reason)
+ alpm_errno_t reason)
{
int doremove = 0;
QUESTION(handle, ALPM_QUESTION_CORRUPTED_PKG, (char *)filepath,
@@ -783,7 +781,7 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas)
alpm_delta_t *d = i->data;
char *filepath = _alpm_filecache_find(handle, d->delta);
- if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_CSUM_MD5)) {
+ if(_alpm_test_checksum(filepath, d->delta_md5, ALPM_PKG_VALIDATION_MD5SUM)) {
errors = alpm_list_add(errors, filepath);
} else {
FREE(filepath);
@@ -804,11 +802,96 @@ static int validate_deltas(alpm_handle_t *handle, alpm_list_t *deltas)
return 0;
}
+static struct dload_payload *build_payload(alpm_handle_t *handle,
+ const char *filename, size_t size, alpm_list_t *servers)
+{
+ struct dload_payload *payload;
+
+ CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
+ STRDUP(payload->remote_name, filename, RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
+ payload->max_size = size;
+ payload->servers = servers;
+ return payload;
+}
+
+static int find_dl_candidates(alpm_db_t *repo, alpm_list_t **files, alpm_list_t **deltas)
+{
+ alpm_list_t *i;
+ alpm_handle_t *handle = repo->handle;
+
+ for(i = handle->trans->add; i; i = i->next) {
+ alpm_pkg_t *spkg = i->data;
+
+ if(spkg->origin != ALPM_PKG_FROM_FILE && repo == spkg->origin_data.db) {
+ alpm_list_t *delta_path = spkg->delta_path;
+
+ if(!repo->servers) {
+ handle->pm_errno = ALPM_ERR_SERVER_NONE;
+ _alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n",
+ alpm_strerror(handle->pm_errno), repo->treename);
+ return 1;
+ }
+
+ if(delta_path) {
+ /* using deltas */
+ alpm_list_t *dlts;
+ for(dlts = delta_path; dlts; dlts = dlts->next) {
+ alpm_delta_t *delta = dlts->data;
+ if(delta->download_size != 0) {
+ struct dload_payload *payload = build_payload(
+ handle, delta->delta, delta->delta_size, repo->servers);
+ ASSERT(payload, return -1);
+ *files = alpm_list_add(*files, payload);
+ }
+ /* keep a list of all the delta files for md5sums */
+ *deltas = alpm_list_add(*deltas, delta);
+ }
+
+ } else if(spkg->download_size != 0) {
+ struct dload_payload *payload;
+ ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
+ payload = build_payload(handle, spkg->filename, spkg->size, repo->servers);
+ ASSERT(payload, return -1);
+ *files = alpm_list_add(*files, payload);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int download_single_file(alpm_handle_t *handle, struct dload_payload *payload,
+ const char *cachedir)
+{
+ const alpm_list_t *server;
+
+ payload->handle = handle;
+ payload->allow_resume = 1;
+
+ for(server = payload->servers; server; server = server->next) {
+ const char *server_url = server->data;
+ size_t len;
+
+ /* print server + filename into a buffer */
+ len = strlen(server_url) + strlen(payload->remote_name) + 2;
+ MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+ snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name);
+
+ if(_alpm_download(payload, cachedir, NULL) != -1) {
+ return 0;
+ }
+
+ FREE(payload->fileurl);
+ payload->unlink_on_fail = 0;
+ }
+
+ return -1;
+}
+
static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)
{
const char *cachedir;
- alpm_list_t *i, *j;
- alpm_list_t *files = NULL;
+ alpm_list_t *i, *files = NULL;
int errors = 0;
cachedir = _alpm_filecache_setup(handle);
@@ -827,93 +910,53 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)
handle->totaldlcb(total_size);
}
- /* group sync records by repository and download */
for(i = handle->dbs_sync; i; i = i->next) {
- alpm_db_t *current = i->data;
-
- for(j = handle->trans->add; j; j = j->next) {
- alpm_pkg_t *spkg = j->data;
-
- if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) {
- alpm_list_t *delta_path = spkg->delta_path;
- if(delta_path) {
- /* using deltas */
- alpm_list_t *dlts;
- for(dlts = delta_path; dlts; dlts = dlts->next) {
- alpm_delta_t *delta = dlts->data;
- if(delta->download_size != 0) {
- struct dload_payload *dpayload;
-
- CALLOC(dpayload, 1, sizeof(*dpayload), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- STRDUP(dpayload->remote_name, delta->delta, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- dpayload->max_size = delta->delta_size;
-
- files = alpm_list_add(files, dpayload);
- }
- /* keep a list of all the delta files for md5sums */
- *deltas = alpm_list_add(*deltas, delta);
- }
+ errors += find_dl_candidates(i->data, &files, deltas);
+ }
- } else if(spkg->download_size != 0) {
- struct dload_payload *payload;
+ if(files) {
+ /* check for necessary disk space for download */
+ if(handle->checkspace) {
+ off_t *file_sizes;
+ size_t idx, num_files;
+ int ret;
- ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
- CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- STRDUP(payload->remote_name, spkg->filename, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- payload->max_size = spkg->size;
+ _alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space for download\n");
- files = alpm_list_add(files, payload);
- }
+ num_files = alpm_list_count(files);
+ CALLOC(file_sizes, num_files, sizeof(off_t), goto finish);
+ for(i = files, idx = 0; i; i = i->next, idx++) {
+ const struct dload_payload *payload = i->data;
+ file_sizes[idx] = payload->max_size;
}
- }
- if(files) {
- if(!current->servers) {
- handle->pm_errno = ALPM_ERR_SERVER_NONE;
- _alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n",
- alpm_strerror(handle->pm_errno), current->treename);
+ ret = _alpm_check_downloadspace(handle, cachedir, num_files, file_sizes);
+ free(file_sizes);
+
+ if(ret != 0) {
errors++;
- continue;
+ goto finish;
}
+ }
- EVENT(handle, ALPM_EVENT_RETRIEVE_START, current->treename, NULL);
- for(j = files; j; j = j->next) {
- struct dload_payload *payload = j->data;
- alpm_list_t *server;
- int ret = -1;
- for(server = current->servers; server; server = server->next) {
- const char *server_url = server->data;
- size_t len;
-
- /* print server + filename into a buffer */
- len = strlen(server_url) + strlen(payload->remote_name) + 2;
- MALLOC(payload->fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- snprintf(payload->fileurl, len, "%s/%s", server_url, payload->remote_name);
- payload->handle = handle;
- payload->allow_resume = 1;
-
- ret = _alpm_download(payload, cachedir, NULL);
- if(ret != -1) {
- break;
- }
- FREE(payload->fileurl);
- payload->unlink_on_fail = 0;
- }
- if(ret == -1) {
- errors++;
- _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files from %s\n"),
- current->treename);
- }
+ EVENT(handle, ALPM_EVENT_RETRIEVE_START, NULL, NULL);
+ for(i = files; i; i = i->next) {
+ if(download_single_file(handle, i->data, cachedir) == -1) {
+ errors++;
+ _alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n"));
}
-
- alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset);
- FREELIST(files);
}
}
- for(j = handle->trans->add; j; j = j->next) {
- alpm_pkg_t *pkg = j->data;
+finish:
+ if(files) {
+ alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_reset);
+ FREELIST(files);
+ }
+
+ for(i = handle->trans->add; i; i = i->next) {
+ alpm_pkg_t *pkg = i->data;
pkg->infolevel &= ~INFRQ_DSIZE;
pkg->download_size = 0;
}
@@ -934,7 +977,8 @@ static int check_validity(alpm_handle_t *handle,
char *path;
alpm_siglist_t *siglist;
alpm_siglevel_t level;
- enum _alpm_errno_t error;
+ alpm_pkgvalidation_t validation;
+ alpm_errno_t error;
};
size_t current = 0, current_bytes = 0;
alpm_list_t *i, *errors = NULL;
@@ -943,12 +987,12 @@ static int check_validity(alpm_handle_t *handle,
EVENT(handle, ALPM_EVENT_INTEGRITY_START, NULL, NULL);
for(i = handle->trans->add; i; i = i->next, current++) {
- struct validity v = { i->data, NULL, NULL, 0, 0 };
+ struct validity v = { i->data, NULL, NULL, 0, 0, 0 };
int percent = (int)(((double)current_bytes / total_bytes) * 100);
PROGRESS(handle, ALPM_PROGRESS_INTEGRITY_START, "", percent,
total, current);
- if(v.pkg->origin == PKG_FROM_FILE) {
+ if(v.pkg->origin == ALPM_PKG_FROM_FILE) {
continue; /* pkg_load() has been already called, this package is valid */
}
@@ -957,7 +1001,7 @@ static int check_validity(alpm_handle_t *handle,
v.level = alpm_db_get_siglevel(alpm_pkg_get_db(v.pkg));
if(_alpm_pkg_validate_internal(handle, v.path, v.pkg,
- v.level, &v.siglist) == -1) {
+ v.level, &v.siglist, &v.validation) == -1) {
v.error = handle->pm_errno;
struct validity *invalid = malloc(sizeof(struct validity));
memcpy(invalid, &v, sizeof(struct validity));
@@ -966,6 +1010,7 @@ static int check_validity(alpm_handle_t *handle,
alpm_siglist_cleanup(v.siglist);
free(v.siglist);
free(v.path);
+ v.pkg->validation = v.validation;
}
}
@@ -1023,7 +1068,7 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data,
PROGRESS(handle, ALPM_PROGRESS_LOAD_START, "", percent,
total, current);
- if(spkg->origin == PKG_FROM_FILE) {
+ if(spkg->origin == ALPM_PKG_FROM_FILE) {
continue; /* pkg_load() has been already called, this package is valid */
}
@@ -1045,6 +1090,8 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data,
free(filepath);
/* copy over the install reason */
pkgfile->reason = spkg->reason;
+ /* copy over validation method */
+ pkgfile->validation = spkg->validation;
i->data = pkgfile;
/* spkg has been removed from the target list, so we can free the
* sync-specific fields */
@@ -1091,7 +1138,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)
* realistically if there are small and huge packages involved */
for(i = trans->add; i; i = i->next) {
alpm_pkg_t *spkg = i->data;
- if(spkg->origin != PKG_FROM_FILE) {
+ if(spkg->origin != ALPM_PKG_FROM_FILE) {
total_bytes += spkg->size;
}
total++;
@@ -1120,7 +1167,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)
trans->state = STATE_COMMITING;
/* fileconflict check */
- if(!(trans->flags & ALPM_TRANS_FLAG_FORCE)) {
+ if(!(trans->flags & (ALPM_TRANS_FLAG_FORCE|ALPM_TRANS_FLAG_DBONLY))) {
EVENT(handle, ALPM_EVENT_FILECONFLICTS_START, NULL, NULL);
_alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n");
@@ -1145,7 +1192,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)
_alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space\n");
if(_alpm_check_diskspace(handle) == -1) {
- _alpm_log(handle, ALPM_LOG_ERROR, "%s\n", _("not enough free disk space"));
+ _alpm_log(handle, ALPM_LOG_ERROR, _("not enough free disk space\n"));
return -1;
}
diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h
index 472d1dfc..496f5258 100644
--- a/lib/libalpm/sync.h
+++ b/lib/libalpm/sync.h
@@ -1,7 +1,7 @@
/*
* sync.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index cb97a4aa..08f70dd7 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -1,7 +1,7 @@
/*
* trans.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
@@ -21,8 +21,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -278,8 +276,8 @@ static int grep(const char *fn, const char *needle)
int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath,
const char *script, const char *ver, const char *oldver, int is_archive)
{
- char cmdline[PATH_MAX];
- char *argv[] = { "sh", "-c", cmdline, NULL };
+ char arg0[64], arg1[3], cmdline[PATH_MAX];
+ char *argv[] = { arg0, arg1, cmdline, NULL };
char *tmpdir, *scriptfn = NULL, *scriptpath;
int retval = 0;
size_t len;
@@ -295,6 +293,9 @@ int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath,
return 0;
}
+ strcpy(arg0, SCRIPTLET_SHELL);
+ strcpy(arg1, "-c");
+
/* create a directory in $root/tmp/ for copying/extracting the scriptlet */
len = strlen(handle->root) + strlen("tmp/alpm_XXXXXX") + 1;
MALLOC(tmpdir, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
@@ -345,7 +346,7 @@ int _alpm_runscriptlet(alpm_handle_t *handle, const char *filepath,
_alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\"\n", cmdline);
- retval = _alpm_run_chroot(handle, "/bin/sh", argv);
+ retval = _alpm_run_chroot(handle, SCRIPTLET_SHELL, argv);
cleanup:
if(scriptfn && unlink(scriptfn)) {
diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h
index ff944b09..acde9219 100644
--- a/lib/libalpm/trans.h
+++ b/lib/libalpm/trans.h
@@ -1,7 +1,7 @@
/*
* trans.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 0e5e8a00..033058a0 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -22,24 +22,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
-#include <stdio.h>
#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <dirent.h>
-#include <fcntl.h>
#include <time.h>
#include <syslog.h>
#include <errno.h>
#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/wait.h>
#include <locale.h> /* setlocale */
+#include <fnmatch.h>
/* libarchive */
#include <archive.h>
@@ -62,11 +55,19 @@
#include "trans.h"
#ifndef HAVE_STRSEP
-/* This is a replacement for strsep which is not portable (missing on Solaris).
- * Copyright (c) 2001 by François Gouget <fgouget_at_codeweavers.com> */
-char* strsep(char** str, const char* delims)
+/** Extracts tokens from a string.
+ * Replaces strset which is not portable (missing on Solaris).
+ * Copyright (c) 2001 by François Gouget <fgouget_at_codeweavers.com>
+ * Modifies str to point to the first character after the token if one is
+ * found, or NULL if one is not.
+ * @param str string containing delimited tokens to parse
+ * @param delim character delimiting tokens in str
+ * @return pointer to the first token in str if str is not NULL, NULL if
+ * str is NULL
+ */
+char *strsep(char **str, const char *delims)
{
- char* token;
+ char *token;
if(*str==NULL) {
/* No more tokens */
@@ -93,138 +94,118 @@ int _alpm_makepath(const char *path)
return _alpm_makepath_mode(path, 0755);
}
-/* does the same thing as 'mkdir -p' */
+/** Creates a directory, including parents if needed, similar to 'mkdir -p'.
+ * @param path directory path to create
+ * @param mode permission mode for created directories
+ * @return 0 on success, 1 on error
+ */
int _alpm_makepath_mode(const char *path, mode_t mode)
{
- /* A bit of pointer hell here. Descriptions:
- * orig - a copy of path so we can safely butcher it with strsep
- * str - the current position in the path string (after the delimiter)
- * ptr - the original position of str after calling strsep
- * incr - incrementally generated path for use in stat/mkdir call
- */
- char *orig, *str, *ptr, *incr;
- mode_t oldmask = umask(0000);
+ char *ptr, *str;
+ mode_t oldmask;
int ret = 0;
- orig = strdup(path);
- incr = calloc(strlen(orig) + 1, sizeof(char));
- str = orig;
- while((ptr = strsep(&str, "/"))) {
- if(strlen(ptr)) {
- /* we have another path component- append the newest component to
- * existing string and create one more level of dir structure */
- strcat(incr, "/");
- strcat(incr, ptr);
- if(access(incr, F_OK)) {
- if(mkdir(incr, mode)) {
- ret = 1;
- break;
- }
- }
- }
- }
- free(orig);
- free(incr);
- umask(oldmask);
- return ret;
-}
+ STRDUP(str, path, return 1);
-int _alpm_copyfile(const char *src, const char *dest)
-{
- FILE *in, *out;
- size_t len;
- char *buf;
- int ret = 0;
+ oldmask = umask(0000);
- in = fopen(src, "rb");
- if(in == NULL) {
- return 1;
- }
- out = fopen(dest, "wb");
- if(out == NULL) {
- fclose(in);
- return 1;
- }
+ for(ptr = str; *ptr; ptr++) {
+ /* detect mid-path condition and zero length paths */
+ if(*ptr != '/' || ptr == str || ptr[-1] == '/') {
+ continue;
+ }
- MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, ret = 1; goto cleanup);
+ /* temporarily mask the end of the path */
+ *ptr = '\0';
- /* do the actual file copy */
- while((len = fread(buf, 1, ALPM_BUFFER_SIZE, in))) {
- size_t nwritten = 0;
- nwritten = fwrite(buf, 1, len, out);
- if((nwritten != len) || ferror(out)) {
- ret = -1;
- goto cleanup;
+ if(mkdir(str, mode) < 0 && errno != EEXIST) {
+ ret = 1;
+ goto done;
}
+
+ /* restore path separator */
+ *ptr = '/';
}
- /* chmod dest to permissions of src, as long as it is not a symlink */
- struct stat statbuf;
- if(!stat(src, &statbuf)) {
- if(! S_ISLNK(statbuf.st_mode)) {
- fchmod(fileno(out), statbuf.st_mode);
- }
- } else {
- /* stat was unsuccessful */
+ /* end of the string. add the full path. It will already exist when the path
+ * passed in has a trailing slash. */
+ if(mkdir(str, mode) < 0 && errno != EEXIST) {
ret = 1;
}
-cleanup:
- fclose(in);
- fclose(out);
- free(buf);
+done:
+ umask(oldmask);
+ free(str);
return ret;
}
-/* Trim whitespace and newlines from a string
-*/
-char *_alpm_strtrim(char *str)
+/** Copies a file.
+ * @param src file path to copy from
+ * @param dest file path to copy to
+ * @return 0 on success, 1 on error
+ */
+int _alpm_copyfile(const char *src, const char *dest)
{
- char *pch = str;
+ char *buf;
+ int in, out, ret = 1;
+ ssize_t nread;
+ struct stat st;
- if(*str == '\0') {
- /* string is empty, so we're done. */
- return str;
+ MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1);
+
+ OPEN(in, src, O_RDONLY);
+ do {
+ out = open(dest, O_WRONLY | O_CREAT, 0000);
+ } while(out == -1 && errno == EINTR);
+ if(in < 0 || out < 0) {
+ goto cleanup;
}
- while(isspace((unsigned char)*pch)) {
- pch++;
+ if(fstat(in, &st) || fchmod(out, st.st_mode)) {
+ goto cleanup;
}
- if(pch != str) {
- size_t len = strlen(pch);
- if(len) {
- memmove(str, pch, len + 1);
- } else {
- *str = '\0';
+
+ /* do the actual file copy */
+ while((nread = read(in, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) {
+ ssize_t nwrite = 0;
+ if(nread < 0) {
+ continue;
}
+ do {
+ nwrite = write(out, buf + nwrite, nread);
+ if(nwrite >= 0) {
+ nread -= nwrite;
+ } else if(errno != EINTR) {
+ goto cleanup;
+ }
+ } while(nread > 0);
}
+ ret = 0;
- /* check if there wasn't anything but whitespace in the string. */
- if(*str == '\0') {
- return str;
+cleanup:
+ free(buf);
+ if(in >= 0) {
+ CLOSE(in);
}
-
- pch = (str + (strlen(str) - 1));
- while(isspace((unsigned char)*pch)) {
- pch--;
+ if(out >= 0) {
+ CLOSE(out);
}
- *++pch = '\0';
-
- return str;
+ return ret;
}
-/**
- * Trim trailing newline from a string (if one exists).
+/** Trim trailing newlines from a string (if any exist).
* @param str a single line of text
+ * @param len size of str, if known, else 0
* @return the length of the trimmed string
*/
-size_t _alpm_strip_newline(char *str)
+size_t _alpm_strip_newline(char *str, size_t len)
{
- size_t len;
if(*str == '\0') {
return 0;
}
- len = strlen(str);
+ if(len == 0) {
+ len = strlen(str);
+ }
while(len > 0 && str[len - 1] == '\n') {
len--;
}
@@ -235,9 +216,70 @@ size_t _alpm_strip_newline(char *str)
/* Compression functions */
-/**
- * @brief Unpack a specific file in an archive.
- *
+/** Open an archive for reading and perform the necessary boilerplate.
+ * This takes care of creating the libarchive 'archive' struct, setting up
+ * compression and format options, opening a file descriptor, setting up the
+ * buffer size, and performing a stat on the path once opened.
+ * On error, no file descriptor is opened, and the archive pointer returned
+ * will be set to NULL.
+ * @param handle the context handle
+ * @param path the path of the archive to open
+ * @param buf space for a stat buffer for the given path
+ * @param archive pointer to place the created archive object
+ * @param error error code to set on failure to open archive
+ * @return -1 on failure, >=0 file descriptor on success
+ */
+int _alpm_open_archive(alpm_handle_t *handle, const char *path,
+ struct stat *buf, struct archive **archive, alpm_errno_t error)
+{
+ int fd;
+ size_t bufsize = ALPM_BUFFER_SIZE;
+ errno = 0;
+
+ if((*archive = archive_read_new()) == NULL) {
+ RET_ERR(handle, ALPM_ERR_LIBARCHIVE, -1);
+ }
+
+ archive_read_support_compression_all(*archive);
+ archive_read_support_format_all(*archive);
+
+ _alpm_log(handle, ALPM_LOG_DEBUG, "opening archive %s\n", path);
+ OPEN(fd, path, O_RDONLY);
+ if(fd < 0) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("could not open file %s: %s\n"), path, strerror(errno));
+ goto error;
+ }
+
+ if(fstat(fd, buf) != 0) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("could not stat file %s: %s\n"), path, strerror(errno));
+ goto error;
+ }
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+ if(buf->st_blksize > ALPM_BUFFER_SIZE) {
+ bufsize = buf->st_blksize;
+ }
+#endif
+
+ if(archive_read_open_fd(*archive, fd, bufsize) != ARCHIVE_OK) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"),
+ path, archive_error_string(*archive));
+ goto error;
+ }
+
+ return fd;
+
+error:
+ archive_read_finish(*archive);
+ *archive = NULL;
+ if(fd >= 0) {
+ CLOSE(fd);
+ }
+ RET_ERR(handle, error, -1);
+}
+
+/** Unpack a specific file in an archive.
* @param handle the context handle
* @param archive the archive to unpack
* @param prefix where to extract the files
@@ -258,46 +300,33 @@ int _alpm_unpack_single(alpm_handle_t *handle, const char *archive,
return ret;
}
-/**
- * @brief Unpack a list of files in an archive.
- *
+/** Unpack a list of files in an archive.
* @param handle the context handle
- * @param archive the archive to unpack
+ * @param path the archive to unpack
* @param prefix where to extract the files
* @param list a list of files within the archive to unpack or NULL for all
* @param breakfirst break after the first entry found
- *
* @return 0 on success, 1 on failure
*/
-int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
+int _alpm_unpack(alpm_handle_t *handle, const char *path, const char *prefix,
alpm_list_t *list, int breakfirst)
{
int ret = 0;
mode_t oldmask;
- struct archive *_archive;
+ struct archive *archive;
struct archive_entry *entry;
- int cwdfd;
-
- if((_archive = archive_read_new()) == NULL) {
- RET_ERR(handle, ALPM_ERR_LIBARCHIVE, 1);
- }
-
- archive_read_support_compression_all(_archive);
- archive_read_support_format_all(_archive);
+ struct stat buf;
+ int fd, cwdfd;
- if(archive_read_open_filename(_archive, archive,
- ALPM_BUFFER_SIZE) != ARCHIVE_OK) {
- _alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"), archive,
- archive_error_string(_archive));
- RET_ERR(handle, ALPM_ERR_PKG_OPEN, 1);
+ fd = _alpm_open_archive(handle, path, &buf, &archive, ALPM_ERR_PKG_OPEN);
+ if(fd < 0) {
+ return 1;
}
oldmask = umask(0022);
/* save the cwd so we can restore it later */
- do {
- cwdfd = open(".", O_RDONLY);
- } while(cwdfd == -1 && errno == EINTR);
+ OPEN(cwdfd, ".", O_RDONLY);
if(cwdfd < 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
}
@@ -310,19 +339,12 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
goto cleanup;
}
- while(archive_read_next_header(_archive, &entry) == ARCHIVE_OK) {
- const struct stat *st;
- const char *entryname; /* the name of the file in the archive */
+ while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
+ const char *entryname;
+ mode_t mode;
- st = archive_entry_stat(entry);
entryname = archive_entry_pathname(entry);
- if(S_ISREG(st->st_mode)) {
- archive_entry_set_perm(entry, 0644);
- } else if(S_ISDIR(st->st_mode)) {
- archive_entry_set_perm(entry, 0755);
- }
-
/* If specific files were requested, skip entries that don't match. */
if(list) {
char *entry_prefix = strdup(entryname);
@@ -333,7 +355,7 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
char *found = alpm_list_find_str(list, entry_prefix);
free(entry_prefix);
if(!found) {
- if(archive_read_data_skip(_archive) != ARCHIVE_OK) {
+ if(archive_read_data_skip(archive) != ARCHIVE_OK) {
ret = 1;
goto cleanup;
}
@@ -343,15 +365,22 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
}
}
+ mode = archive_entry_mode(entry);
+ if(S_ISREG(mode)) {
+ archive_entry_set_perm(entry, 0644);
+ } else if(S_ISDIR(mode)) {
+ archive_entry_set_perm(entry, 0755);
+ }
+
/* Extract the archive entry. */
- int readret = archive_read_extract(_archive, entry, 0);
+ int readret = archive_read_extract(archive, entry, 0);
if(readret == ARCHIVE_WARN) {
/* operation succeeded but a non-critical error was encountered */
_alpm_log(handle, ALPM_LOG_WARNING, _("warning given when extracting %s (%s)\n"),
- entryname, archive_error_string(_archive));
+ entryname, archive_error_string(archive));
} else if(readret != ARCHIVE_OK) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not extract %s (%s)\n"),
- entryname, archive_error_string(_archive));
+ entryname, archive_error_string(archive));
ret = 1;
goto cleanup;
}
@@ -363,63 +392,20 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
cleanup:
umask(oldmask);
- archive_read_finish(_archive);
+ archive_read_finish(archive);
+ CLOSE(fd);
if(cwdfd >= 0) {
if(fchdir(cwdfd) != 0) {
_alpm_log(handle, ALPM_LOG_ERROR,
_("could not restore working directory (%s)\n"), strerror(errno));
}
- close(cwdfd);
+ CLOSE(cwdfd);
}
return ret;
}
-/* does the same thing as 'rm -rf' */
-int _alpm_rmrf(const char *path)
-{
- int errflag = 0;
- struct dirent *dp;
- DIR *dirp;
- struct stat st;
-
- if(_alpm_lstat(path, &st) == 0) {
- if(!S_ISDIR(st.st_mode)) {
- if(!unlink(path)) {
- return 0;
- } else {
- if(errno == ENOENT) {
- return 0;
- } else {
- return 1;
- }
- }
- } else {
- dirp = opendir(path);
- if(!dirp) {
- return 1;
- }
- for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- if(dp->d_name) {
- if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) {
- char name[PATH_MAX];
- sprintf(name, "%s/%s", path, dp->d_name);
- errflag += _alpm_rmrf(name);
- }
- }
- }
- closedir(dirp);
- if(rmdir(path)) {
- errflag++;
- }
- }
- return errflag;
- }
- return 0;
-}
-
-/**
- * Determine if there are files in a directory
+/** Determine if there are files in a directory.
* @param handle the context handle
* @param path the full absolute directory path
* @param full_count whether to return an exact count of files
@@ -460,6 +446,13 @@ ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path,
return files;
}
+/** Write formatted message to log.
+ * @param handle the context handle
+ * @param format formatted string to write out
+ * @param args formatting arguments
+ * @return 0 or number of characters written on success, vfprintf return value
+ * on error
+ */
int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args)
{
int ret = 0;
@@ -491,16 +484,20 @@ int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args)
return ret;
}
-int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[])
+/** Execute a command with arguments in a chroot.
+ * @param handle the context handle
+ * @param cmd command to execute
+ * @param argv arguments to pass to cmd
+ * @return 0 on success, 1 on error
+ */
+int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[])
{
pid_t pid;
int pipefd[2], cwdfd;
int retval = 0;
/* save the cwd so we can restore it later */
- do {
- cwdfd = open(".", O_RDONLY);
- } while(cwdfd == -1 && errno == EINTR);
+ OPEN(cwdfd, ".", O_RDONLY);
if(cwdfd < 0) {
_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
}
@@ -513,7 +510,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]
}
_alpm_log(handle, ALPM_LOG_DEBUG, "executing \"%s\" under chroot \"%s\"\n",
- path, handle->root);
+ cmd, handle->root);
/* Flush open fds before fork() to avoid cloning buffers */
fflush(NULL);
@@ -534,12 +531,12 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]
if(pid == 0) {
/* this code runs for the child only (the actual chroot/exec) */
- close(1);
- close(2);
+ CLOSE(1);
+ CLOSE(2);
while(dup2(pipefd[1], 1) == -1 && errno == EINTR);
while(dup2(pipefd[1], 2) == -1 && errno == EINTR);
- close(pipefd[0]);
- close(pipefd[1]);
+ CLOSE(pipefd[0]);
+ CLOSE(pipefd[1]);
/* use fprintf instead of _alpm_log to send output through the parent */
if(chroot(handle->root) != 0) {
@@ -552,7 +549,8 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]
exit(1);
}
umask(0022);
- execv(path, argv);
+ execv(cmd, argv);
+ /* execv only returns if there was an error */
fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno));
exit(1);
} else {
@@ -560,10 +558,10 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]
int status;
FILE *pipe_file;
- close(pipefd[1]);
+ CLOSE(pipefd[1]);
pipe_file = fdopen(pipefd[0], "r");
if(pipe_file == NULL) {
- close(pipefd[0]);
+ CLOSE(pipefd[0]);
retval = 1;
} else {
while(!feof(pipe_file)) {
@@ -605,12 +603,16 @@ cleanup:
_alpm_log(handle, ALPM_LOG_ERROR,
_("could not restore working directory (%s)\n"), strerror(errno));
}
- close(cwdfd);
+ CLOSE(cwdfd);
}
return retval;
}
+/** Run ldconfig in a chroot.
+ * @param handle the context handle
+ * @return 0 on success, 1 on error
+ */
int _alpm_ldconfig(alpm_handle_t *handle)
{
char line[PATH_MAX];
@@ -621,7 +623,9 @@ int _alpm_ldconfig(alpm_handle_t *handle)
if(access(line, F_OK) == 0) {
snprintf(line, PATH_MAX, "%ssbin/ldconfig", handle->root);
if(access(line, X_OK) == 0) {
- char *argv[] = { "ldconfig", NULL };
+ char arg0[32];
+ char *argv[] = { arg0, NULL };
+ strcpy(arg0, "ldconfig");
return _alpm_run_chroot(handle, "/sbin/ldconfig", argv);
}
}
@@ -629,8 +633,13 @@ int _alpm_ldconfig(alpm_handle_t *handle)
return 0;
}
-/* Helper function for comparing strings using the
- * alpm "compare func" signature */
+/** Helper function for comparing strings using the alpm "compare func"
+ * signature.
+ * @param s1 first string to be compared
+ * @param s2 second string to be compared
+ * @return 0 if strings are equal, positive int if first unequal character
+ * has a greater value in s1, negative if it has a greater value in s2
+ */
int _alpm_str_cmp(const void *s1, const void *s2)
{
return strcmp(s1, s2);
@@ -671,7 +680,8 @@ const char *_alpm_filecache_setup(alpm_handle_t *handle)
{
struct stat buf;
alpm_list_t *i;
- char *cachedir, *tmpdir;
+ char *cachedir;
+ const char *tmpdir;
/* Loop through the cache dirs until we find a usable directory */
for(i = handle->cachedirs; i; i = i->next) {
@@ -687,7 +697,7 @@ const char *_alpm_filecache_setup(alpm_handle_t *handle)
} else if(!S_ISDIR(buf.st_mode)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"skipping cachedir, not a directory: %s\n", cachedir);
- } else if(access(cachedir, W_OK) != 0) {
+ } else if(_alpm_access(handle, NULL, cachedir, W_OK) != 0) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"skipping cachedir, not writable: %s\n", cachedir);
} else if(!(buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))) {
@@ -739,51 +749,64 @@ int _alpm_lstat(const char *path, struct stat *buf)
}
#ifdef HAVE_LIBSSL
+/** Compute the MD5 message digest of a file.
+ * @param path file path of file to compute MD5 digest of
+ * @param output string to hold computed MD5 digest
+ * @return 0 on success, 1 on file open error, 2 on file read error
+ */
static int md5_file(const char *path, unsigned char output[16])
{
- FILE *f;
- size_t n;
MD5_CTX ctx;
unsigned char *buf;
+ ssize_t n;
+ int fd;
- CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1);
+ MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1);
- if((f = fopen(path, "rb")) == NULL) {
+ OPEN(fd, path, O_RDONLY);
+ if(fd < 0) {
free(buf);
return 1;
}
MD5_Init(&ctx);
- while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) {
+ while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) {
+ if(n < 0) {
+ continue;
+ }
MD5_Update(&ctx, buf, n);
}
- MD5_Final(output, &ctx);
-
- memset(&ctx, 0, sizeof(MD5_CTX));
+ CLOSE(fd);
free(buf);
- if(ferror(f) != 0) {
- fclose(f);
+ if(n < 0) {
return 2;
}
- fclose(f);
+ MD5_Final(output, &ctx);
return 0;
}
/* third param is so we match the PolarSSL definition */
+/** Compute the SHA-224 or SHA-256 message digest of a file.
+ * @param path file path of file to compute SHA2 digest of
+ * @param output string to hold computed SHA2 digest
+ * @param is224 use SHA-224 instead of SHA-256
+ * @return 0 on success, 1 on file open error, 2 on file read error
+ */
static int sha2_file(const char *path, unsigned char output[32], int is224)
{
- FILE *f;
- size_t n;
SHA256_CTX ctx;
unsigned char *buf;
+ ssize_t n;
+ int fd;
- CALLOC(buf, ALPM_BUFFER_SIZE, sizeof(unsigned char), return 1);
+ MALLOC(buf, (size_t)ALPM_BUFFER_SIZE, return 1);
- if((f = fopen(path, "rb")) == NULL) {
+ OPEN(fd, path, O_RDONLY);
+ if(fd < 0) {
free(buf);
return 1;
}
@@ -794,7 +817,10 @@ static int sha2_file(const char *path, unsigned char output[32], int is224)
SHA256_Init(&ctx);
}
- while((n = fread(buf, 1, ALPM_BUFFER_SIZE, f)) > 0) {
+ while((n = read(fd, buf, ALPM_BUFFER_SIZE)) > 0 || errno == EINTR) {
+ if(n < 0) {
+ continue;
+ }
if(is224) {
SHA224_Update(&ctx, buf, n);
} else {
@@ -802,24 +828,45 @@ static int sha2_file(const char *path, unsigned char output[32], int is224)
}
}
+ CLOSE(fd);
+ free(buf);
+
+ if(n < 0) {
+ return 2;
+ }
+
if(is224) {
SHA224_Final(output, &ctx);
} else {
SHA256_Final(output, &ctx);
}
+ return 0;
+}
+#endif
- memset(&ctx, 0, sizeof(SHA256_CTX));
- free(buf);
+/** Create a string representing bytes in hexadecimal.
+ * @param bytes the bytes to represent in hexadecimal
+ * @param size number of bytes to consider
+ * @return a NULL terminated string with the hexadecimal representation of
+ * bytes or NULL on error. This string must be freed.
+ */
+static char *hex_representation(unsigned char *bytes, size_t size)
+{
+ static const char *hex_digits = "0123456789abcdef";
+ char *str;
+ size_t i;
- if(ferror(f) != 0) {
- fclose(f);
- return 2;
+ MALLOC(str, 2 * size + 1, return NULL);
+
+ for (i = 0; i < size; i++) {
+ str[2 * i] = hex_digits[bytes[i] >> 4];
+ str[2 * i + 1] = hex_digits[bytes[i] & 0x0f];
}
- fclose(f);
- return 0;
+ str[2 * size] = '\0';
+
+ return str;
}
-#endif
/** Get the md5 sum of file.
* @param filename name of the file
@@ -829,28 +876,15 @@ static int sha2_file(const char *path, unsigned char output[32], int is224)
char SYMEXPORT *alpm_compute_md5sum(const char *filename)
{
unsigned char output[16];
- char *md5sum;
- int ret, i;
ASSERT(filename != NULL, return NULL);
- /* allocate 32 chars plus 1 for null */
- CALLOC(md5sum, 33, sizeof(char), return NULL);
/* defined above for OpenSSL, otherwise defined in md5.h */
- ret = md5_file(filename, output);
-
- if(ret > 0) {
- free(md5sum);
+ if(md5_file(filename, output) > 0) {
return NULL;
}
- /* Convert the result to something readable */
- for (i = 0; i < 16; i++) {
- /* sprintf is acceptable here because we know our output */
- sprintf(md5sum +(i * 2), "%02x", output[i]);
- }
-
- return md5sum;
+ return hex_representation(output, 16);
}
/** Get the sha256 sum of file.
@@ -861,39 +895,33 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename)
char SYMEXPORT *alpm_compute_sha256sum(const char *filename)
{
unsigned char output[32];
- char *sha256sum;
- int ret, i;
ASSERT(filename != NULL, return NULL);
- /* allocate 64 chars plus 1 for null */
- CALLOC(sha256sum, 65, sizeof(char), return NULL);
/* defined above for OpenSSL, otherwise defined in sha2.h */
- ret = sha2_file(filename, output, 0);
-
- if(ret > 0) {
- free(sha256sum);
+ if(sha2_file(filename, output, 0) > 0) {
return NULL;
}
- /* Convert the result to something readable */
- for (i = 0; i < 32; i++) {
- /* sprintf is acceptable here because we know our output */
- sprintf(sha256sum +(i * 2), "%02x", output[i]);
- }
-
- return sha256sum;
+ return hex_representation(output, 32);
}
+/** Calculates a file's MD5 or SHA2 digest and compares it to an expected value.
+ * @param filepath path of the file to check
+ * @param expected hash value to compare against
+ * @param type digest type to use
+ * @return 0 if file matches the expected hash, 1 if they do not match, -1 on
+ * error
+ */
int _alpm_test_checksum(const char *filepath, const char *expected,
- enum _alpm_csum type)
+ alpm_pkgvalidation_t type)
{
char *computed;
int ret;
- if(type == ALPM_CSUM_MD5) {
+ if(type == ALPM_PKG_VALIDATION_MD5SUM) {
computed = alpm_compute_md5sum(filepath);
- } else if(type == ALPM_CSUM_SHA256) {
+ } else if(type == ALPM_PKG_VALIDATION_SHA256SUM) {
computed = alpm_compute_sha256sum(filepath);
} else {
return -1;
@@ -912,18 +940,24 @@ int _alpm_test_checksum(const char *filepath, const char *expected,
}
/* Note: does NOT handle sparse files on purpose for speed. */
+/** TODO.
+ * Does not handle sparse files on purpose for speed.
+ * @param a
+ * @param b
+ * @return
+ */
int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
{
- char *i = NULL;
- int64_t offset;
- int done = 0;
-
/* ensure we start populating our line buffer at the beginning */
b->line_offset = b->line;
while(1) {
+ size_t block_remaining;
+ char *eol;
+
/* have we processed this entire block? */
if(b->block + b->block_size == b->block_offset) {
+ int64_t offset;
if(b->ret == ARCHIVE_EOF) {
/* reached end of archive on the last read, now we are out of data */
goto cleanup;
@@ -933,20 +967,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
b->ret = archive_read_data_block(a, (void *)&b->block,
&b->block_size, &offset);
b->block_offset = b->block;
+ block_remaining = b->block_size;
/* error, cleanup */
if(b->ret < ARCHIVE_OK) {
goto cleanup;
}
+ } else {
+ block_remaining = b->block + b->block_size - b->block_offset;
}
- /* loop through the block looking for EOL characters */
- for(i = b->block_offset; i < (b->block + b->block_size); i++) {
- /* check if read value was null or newline */
- if(*i == '\0' || *i == '\n') {
- done = 1;
- break;
- }
+ /* look through the block looking for EOL characters */
+ eol = memchr(b->block_offset, '\n', block_remaining);
+ if(!eol) {
+ eol = memchr(b->block_offset, '\0', block_remaining);
}
/* allocate our buffer, or ensure our existing one is big enough */
@@ -956,29 +990,32 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
b->line_size = b->block_size + 1;
b->line_offset = b->line;
} else {
- size_t needed = (size_t)((b->line_offset - b->line)
- + (i - b->block_offset) + 1);
+ /* note: we know eol > b->block_offset and b->line_offset > b->line,
+ * so we know the result is unsigned and can fit in size_t */
+ size_t new = eol ? (size_t)(eol - b->block_offset) : block_remaining;
+ size_t needed = (size_t)((b->line_offset - b->line) + new + 1);
if(needed > b->max_line_size) {
b->ret = -ERANGE;
goto cleanup;
}
if(needed > b->line_size) {
/* need to realloc + copy data to fit total length */
- char *new;
- CALLOC(new, needed, sizeof(char), b->ret = -ENOMEM; goto cleanup);
- memcpy(new, b->line, b->line_size);
+ char *new_line;
+ CALLOC(new_line, needed, sizeof(char), b->ret = -ENOMEM; goto cleanup);
+ memcpy(new_line, b->line, b->line_size);
b->line_size = needed;
- b->line_offset = new + (b->line_offset - b->line);
+ b->line_offset = new_line + (b->line_offset - b->line);
free(b->line);
- b->line = new;
+ b->line = new_line;
}
}
- if(done) {
- size_t len = (size_t)(i - b->block_offset);
+ if(eol) {
+ size_t len = (size_t)(eol - b->block_offset);
memcpy(b->line_offset, b->block_offset, len);
b->line_offset[len] = '\0';
- b->block_offset = ++i;
+ b->block_offset = eol + 1;
+ b->real_line_size = b->line_offset + len - b->line;
/* this is the main return point; from here you can read b->line */
return ARCHIVE_OK;
} else {
@@ -986,11 +1023,12 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
size_t len = (size_t)(b->block + b->block_size - b->block_offset);
memcpy(b->line_offset, b->block_offset, len);
b->line_offset += len;
- b->block_offset = i;
+ b->block_offset = b->block + b->block_size;
/* there was no new data, return what is left; saved ARCHIVE_EOF will be
* returned on next call */
if(len == 0) {
b->line_offset[0] = '\0';
+ b->real_line_size = b->line_offset - b->line;
return ARCHIVE_OK;
}
}
@@ -1005,6 +1043,14 @@ cleanup:
}
}
+/** Parse a full package specifier.
+ * @param target package specifier to parse, such as: "pacman-4.0.1-2",
+ * "pacman-4.01-2/", or "pacman-4.0.1-2/desc"
+ * @param name to hold package name
+ * @param version to hold package version
+ * @param name_hash to hold package name hash
+ * @return 0 on success, -1 on error
+ */
int _alpm_splitname(const char *target, char **name, char **version,
unsigned long *name_hash)
{
@@ -1057,8 +1103,7 @@ int _alpm_splitname(const char *target, char **name, char **version,
return 0;
}
-/**
- * Hash the given string to an unsigned long value.
+/** Hash the given string to an unsigned long value.
* This is the standard sdbm hashing algorithm.
* @param str string to hash
* @return the hash value of the given string
@@ -1072,12 +1117,17 @@ unsigned long _alpm_hash_sdbm(const char *str)
return hash;
}
while((c = *str++)) {
- hash = c + (hash << 6) + (hash << 16) - hash;
+ hash = c + hash * 65599;
}
return hash;
}
+/** Convert a string to a file offset.
+ * This parses bare positive integers only.
+ * @param line string to convert
+ * @return off_t on success, -1 on error
+ */
off_t _alpm_strtoofft(const char *line)
{
char *end;
@@ -1089,13 +1139,13 @@ off_t _alpm_strtoofft(const char *line)
return (off_t)-1;
}
result = strtoull(line, &end, 10);
- if (result == 0 && end == line) {
+ if(result == 0 && end == line) {
/* line was not a number */
return (off_t)-1;
- } else if (result == ULLONG_MAX && errno == ERANGE) {
+ } else if(result == ULLONG_MAX && errno == ERANGE) {
/* line does not fit in unsigned long long */
return (off_t)-1;
- } else if (*end) {
+ } else if(*end) {
/* line began with a number but has junk left over at the end */
return (off_t)-1;
}
@@ -1103,8 +1153,16 @@ off_t _alpm_strtoofft(const char *line)
return (off_t)result;
}
-time_t _alpm_parsedate(const char *line)
+/** Parses a date into an alpm_time_t struct.
+ * @param line date to parse
+ * @return time struct on success, 0 on error
+ */
+alpm_time_t _alpm_parsedate(const char *line)
{
+ char *end;
+ long long result;
+ errno = 0;
+
if(isalpha((unsigned char)line[0])) {
/* initialize to null in case of failure */
struct tm tmp_tm;
@@ -1112,13 +1170,27 @@ time_t _alpm_parsedate(const char *line)
setlocale(LC_TIME, "C");
strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);
setlocale(LC_TIME, "");
- return mktime(&tmp_tm);
+ return (alpm_time_t)mktime(&tmp_tm);
+ }
+
+ result = strtoll(line, &end, 10);
+ if(result == 0 && end == line) {
+ /* line was not a number */
+ errno = EINVAL;
+ return 0;
+ } else if(errno == ERANGE) {
+ /* line does not fit in long long */
+ return 0;
+ } else if(*end) {
+ /* line began with a number but has junk left over at the end */
+ errno = EINVAL;
+ return 0;
}
- return (time_t)atol(line);
+
+ return (alpm_time_t)result;
}
-/**
- * Wrapper around access() which takes a dir and file argument
+/** Wrapper around access() which takes a dir and file argument
* separately and generates an appropriate error message.
* If dir is NULL file will be treated as the whole path.
* @param handle an alpm handle
@@ -1127,13 +1199,12 @@ time_t _alpm_parsedate(const char *line)
* @param amode access mode as described in access()
* @return int value returned by access()
*/
-
int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode)
{
size_t len = 0;
int ret = 0;
- if (dir) {
+ if(dir) {
char *check_path;
len = strlen(dir) + strlen(file) + 1;
@@ -1148,19 +1219,19 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a
}
if(ret != 0) {
- if (amode & R_OK) {
+ if(amode & R_OK) {
_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not readable: %s\n",
dir, file, strerror(errno));
}
- if (amode & W_OK) {
+ if(amode & W_OK) {
_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not writable: %s\n",
dir, file, strerror(errno));
}
- if (amode & X_OK) {
+ if(amode & X_OK) {
_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" is not executable: %s\n",
dir, file, strerror(errno));
}
- if (amode == F_OK) {
+ if(amode == F_OK) {
_alpm_log(handle, ALPM_LOG_DEBUG, "\"%s%s\" does not exist: %s\n",
dir, file, strerror(errno));
}
@@ -1168,8 +1239,30 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a
return ret;
}
+/** Checks whether a string matches a shell wildcard pattern.
+ * Wrapper around fnmatch.
+ * @param pattern pattern to match aganist
+ * @param string string to check against pattern
+ * @return 0 if string matches pattern, non-zero if they don't match and on
+ * error
+ */
+int _alpm_fnmatch(const void *pattern, const void *string)
+{
+ return fnmatch(pattern, string, 0);
+}
+
+void _alpm_alloc_fail(size_t size)
+{
+ fprintf(stderr, "alloc failure: could not allocate %zd bytes\n", size);
+}
+
#ifndef HAVE_STRNDUP
/* A quick and dirty implementation derived from glibc */
+/** Determines the length of a fixed-size string.
+ * @param s string to be measured
+ * @param max maximum number of characters to search for the string end
+ * @return length of s or max, whichever is smaller
+ */
static size_t strnlen(const char *s, size_t max)
{
register const char *p;
@@ -1177,6 +1270,12 @@ static size_t strnlen(const char *s, size_t max)
return (p - s);
}
+/** Copies a string.
+ * Returned string needs to be freed
+ * @param s string to be copied
+ * @param n maximum number of characters to copy
+ * @return pointer to the new string on success, NULL on error
+ */
char *strndup(const char *s, size_t n)
{
size_t len = strnlen(s, n);
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 26fa9044..9bcd59e1 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -1,7 +1,7 @@
/*
* util.h
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
@@ -24,8 +24,6 @@
#ifndef _ALPM_UTIL_H
#define _ALPM_UTIL_H
-#include "config.h"
-
#include "alpm_list.h"
#include "alpm.h"
#include "package.h" /* alpm_pkg_t */
@@ -35,11 +33,13 @@
#include <string.h>
#include <stdarg.h>
#include <stddef.h> /* size_t */
-#include <time.h>
+#include <sys/types.h>
#include <sys/stat.h> /* struct stat */
-#include <archive.h> /* struct archive */
#include <math.h> /* fabs */
#include <float.h> /* DBL_EPSILON */
+#include <fcntl.h> /* open, close */
+
+#include <archive.h> /* struct archive */
#ifdef ENABLE_NLS
#include <libintl.h> /* here so it doesn't need to be included elsewhere */
@@ -49,13 +49,13 @@
#define _(s) s
#endif
-#define ALLOC_FAIL(s) do { fprintf(stderr, "alloc failure: could not allocate %zd bytes\n", s); } while(0)
+void _alpm_alloc_fail(size_t size);
-#define MALLOC(p, s, action) do { p = calloc(1, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0)
-#define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0)
+#define MALLOC(p, s, action) do { p = malloc(s); if(p == NULL) { _alpm_alloc_fail(s); action; } } while(0)
+#define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { _alpm_alloc_fail(l * s); action; } } while(0)
/* This strdup macro is NULL safe- copying NULL will yield NULL */
-#define STRDUP(r, s, action) do { if(s != NULL) { r = strdup(s); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } else { r = NULL; } } while(0)
-#define STRNDUP(r, s, l, action) do { if(s != NULL) { r = strndup(s, l); if(r == NULL) { ALLOC_FAIL(strlen(s)); action; } } else { r = NULL; } } while(0)
+#define STRDUP(r, s, action) do { if(s != NULL) { r = strdup(s); if(r == NULL) { _alpm_alloc_fail(strlen(s)); action; } } else { r = NULL; } } while(0)
+#define STRNDUP(r, s, l, action) do { if(s != NULL) { r = strndup(s, l); if(r == NULL) { _alpm_alloc_fail(l); action; } } else { r = NULL; } } while(0)
#define FREE(p) do { free(p); p = NULL; } while(0)
@@ -82,6 +82,13 @@
#define ALPM_BUFFER_SIZE 8192
#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define OPEN(fd, path, flags) do { fd = open(path, flags | O_BINARY); } while(fd == -1 && errno == EINTR)
+#define CLOSE(fd) do { int _ret; do { _ret = close(fd); } while(_ret == -1 && errno == EINTR); } while(0)
+
/**
* Used as a buffer/state holder for _alpm_archive_fgets().
*/
@@ -90,6 +97,7 @@ struct archive_read_buffer {
char *line_offset;
size_t line_size;
size_t max_line_size;
+ size_t real_line_size;
char *block;
char *block_offset;
@@ -98,39 +106,37 @@ struct archive_read_buffer {
int ret;
};
-enum _alpm_csum {
- ALPM_CSUM_MD5,
- ALPM_CSUM_SHA256,
-};
-
int _alpm_makepath(const char *path);
int _alpm_makepath_mode(const char *path, mode_t mode);
int _alpm_copyfile(const char *src, const char *dest);
-char *_alpm_strtrim(char *str);
-size_t _alpm_strip_newline(char *str);
+size_t _alpm_strip_newline(char *str, size_t len);
+
+int _alpm_open_archive(alpm_handle_t *handle, const char *path,
+ struct stat *buf, struct archive **archive, alpm_errno_t error);
int _alpm_unpack_single(alpm_handle_t *handle, const char *archive,
const char *prefix, const char *filename);
int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
alpm_list_t *list, int breakfirst);
-int _alpm_rmrf(const char *path);
+
ssize_t _alpm_files_in_directory(alpm_handle_t *handle, const char *path, int full_count);
int _alpm_logaction(alpm_handle_t *handle, const char *fmt, va_list args);
-int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]);
+int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[]);
int _alpm_ldconfig(alpm_handle_t *handle);
int _alpm_str_cmp(const void *s1, const void *s2);
char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename);
const char *_alpm_filecache_setup(alpm_handle_t *handle);
int _alpm_lstat(const char *path, struct stat *buf);
-int _alpm_test_checksum(const char *filepath, const char *expected, enum _alpm_csum type);
+int _alpm_test_checksum(const char *filepath, const char *expected, alpm_pkgvalidation_t type);
int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b);
int _alpm_splitname(const char *target, char **name, char **version,
unsigned long *name_hash);
unsigned long _alpm_hash_sdbm(const char *str);
off_t _alpm_strtoofft(const char *line);
-time_t _alpm_parsedate(const char *line);
+alpm_time_t _alpm_parsedate(const char *line);
int _alpm_raw_cmp(const char *first, const char *second);
int _alpm_raw_ncmp(const char *first, const char *second, size_t max);
int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode);
+int _alpm_fnmatch(const void *pattern, const void *string);
#ifndef HAVE_STRSEP
char *strsep(char **, const char *);
diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c
index 6b65a413..269a7016 100644
--- a/lib/libalpm/version.c
+++ b/lib/libalpm/version.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,8 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <string.h>
#include <ctype.h>