summaryrefslogtreecommitdiff
path: root/lib/libalpm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm')
-rw-r--r--lib/libalpm/add.c92
-rw-r--r--lib/libalpm/alpm.h16
-rw-r--r--lib/libalpm/alpm_list.c13
-rw-r--r--lib/libalpm/alpm_list.h1
-rw-r--r--lib/libalpm/base64.c2
-rw-r--r--lib/libalpm/base64.h2
-rw-r--r--lib/libalpm/be_local.c9
-rw-r--r--lib/libalpm/conflict.c10
-rw-r--r--lib/libalpm/db.h2
-rw-r--r--lib/libalpm/diskspace.c102
-rw-r--r--lib/libalpm/diskspace.h2
-rw-r--r--lib/libalpm/dload.h3
-rw-r--r--lib/libalpm/package.c10
-rw-r--r--lib/libalpm/package.h9
-rw-r--r--lib/libalpm/remove.c16
-rw-r--r--lib/libalpm/sync.c193
-rw-r--r--lib/libalpm/util.c88
-rw-r--r--lib/libalpm/util.h5
18 files changed, 349 insertions, 226 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 6c2f0cb6..c6830dce 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -22,7 +22,6 @@
#include <stdlib.h>
#include <errno.h>
-#include <time.h>
#include <string.h>
#include <limits.h>
#include <fcntl.h>
@@ -132,6 +131,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 +157,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",
@@ -282,17 +291,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 +330,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 +363,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 +385,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 +427,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 +448,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
backup->hash = newhash;
}
}
- FREE(entryname_orig);
+ free(entryname_orig);
return errors;
}
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index a93d4e3e..9fda9406 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -27,9 +27,9 @@
extern "C" {
#endif
-#include <sys/types.h> /* for off_t */
-#include <time.h> /* for time_t */
-#include <stdarg.h> /* for va_list */
+#include <inttypes.h> /* int64_t */
+#include <sys/types.h> /* off_t */
+#include <stdarg.h> /* va_list */
#include <alpm_list.h>
@@ -44,6 +44,8 @@ extern "C" {
* @{
*/
+typedef int64_t alpm_time_t;
+
/*
* Enumerations
* These ones are used in multiple contexts, so are forward-declared.
@@ -222,8 +224,8 @@ 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;
} alpm_pgpkey_t;
/** Signature result. Contains the key, status, and validity of a given
@@ -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
diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c
index 15286aa1..cad6d096 100644
--- a/lib/libalpm/alpm_list.c
+++ b/lib/libalpm/alpm_list.c
@@ -576,19 +576,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..9f69e2c2 100644
--- a/lib/libalpm/alpm_list.h
+++ b/lib/libalpm/alpm_list.h
@@ -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/base64.c b/lib/libalpm/base64.c
index 5c9fa814..0d29f656 100644
--- a/lib/libalpm/base64.c
+++ b/lib/libalpm/base64.c
@@ -62,6 +62,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 +125,7 @@ int base64_encode( unsigned char *dst, size_t *dlen,
return( 0 );
}
+#endif
/*
* Decode a base64-formatted buffer
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..21d27481 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -28,7 +28,6 @@
#include <stdint.h> /* intmax_t */
#include <sys/stat.h>
#include <dirent.h>
-#include <time.h>
#include <limits.h> /* PATH_MAX */
/* libalpm */
@@ -69,13 +68,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;
@@ -794,11 +793,11 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq
}
if(info->builddate) {
fprintf(fp, "%%BUILDDATE%%\n"
- "%ld\n\n", info->builddate);
+ "%jd\n\n", (intmax_t)info->builddate);
}
if(info->installdate) {
fprintf(fp, "%%INSTALLDATE%%\n"
- "%ld\n\n", info->installdate);
+ "%jd\n\n", (intmax_t)info->installdate);
}
if(info->packager) {
fprintf(fp, "%%PACKAGER%%\n"
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 32f6f303..486f4bf3 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -318,12 +318,16 @@ const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,
const char *name)
{
size_t i;
- const alpm_file_t *file = filelist->files;
- for(i = 0; i < filelist->count; i++) {
+ const alpm_file_t *file;
+
+ if(!filelist) {
+ return NULL;
+ }
+
+ for(file = filelist->files, i = 0; i < filelist->count; file++, i++) {
if(strcmp(file->name, name) == 0) {
return file;
}
- file++;
}
return NULL;
}
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index 224bfbeb..a1249d3e 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -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/diskspace.c b/lib/libalpm/diskspace.c
index fe2036d5..cfd6402c 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -55,6 +55,17 @@ static int mount_point_cmp(const void *p1, const void *p2)
return -strcmp(mp1->mount_dir, mp2->mount_dir);
}
+static void mount_point_list_free(alpm_list_t *mount_points)
+{
+ alpm_list_t *i;
+
+ for(i = mount_points; i; i = i->next) {
+ alpm_mountpoint_t *data = i->data;
+ FREE(data->mount_dir);
+ }
+ FREELIST(mount_points);
+}
+
static alpm_list_t *mount_point_list(alpm_handle_t *handle)
{
alpm_list_t *mount_points = NULL, *ptr;
@@ -232,6 +243,72 @@ static int calculate_installed_size(alpm_handle_t *handle,
return 0;
}
+static int check_mountpoint(alpm_handle_t *handle, alpm_mountpoint_t *mp)
+{
+ /* cushion is roughly min(5% capacity, 20MiB) */
+ fsblkcnt_t fivepc = (mp->fsp.f_blocks / 20) + 1;
+ fsblkcnt_t twentymb = (20 * 1024 * 1024 / mp->fsp.f_bsize) + 1;
+ fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb;
+ blkcnt_t needed = mp->max_blocks_needed + cushion;
+
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "partition %s, needed %jd, cushion %ju, free %ju\n",
+ mp->mount_dir, (intmax_t)mp->max_blocks_needed,
+ (uintmax_t)cushion, (uintmax_t)mp->fsp.f_bfree);
+ if(needed >= 0 && (fsblkcnt_t)needed > mp->fsp.f_bfree) {
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("Partition %s too full: %jd blocks needed, %jd blocks free\n"),
+ mp->mount_dir, (intmax_t)needed, (uintmax_t)mp->fsp.f_bfree);
+ return 1;
+ }
+ return 0;
+}
+
+int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir,
+ size_t num_files, off_t *file_sizes)
+{
+ alpm_list_t *mount_points;
+ alpm_mountpoint_t *cachedir_mp;
+ size_t j;
+ int error = 0;
+
+ mount_points = mount_point_list(handle);
+ if(mount_points == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n"));
+ return -1;
+ }
+
+ cachedir_mp = match_mount_point(mount_points, cachedir);
+ if(cachedir == NULL) {
+ _alpm_log(handle, ALPM_LOG_ERROR, _("could not determine cachedir mount point %s\n"),
+ cachedir);
+ error = 1;
+ goto finish;
+ }
+
+ /* there's no need to check for a R/O mounted filesystem here, as
+ * _alpm_filecache_setup will never give us a non-writable directory */
+
+ /* round up the size of each file to the nearest block and accumulate */
+ for(j = 0; j < num_files; j++) {
+ cachedir_mp->max_blocks_needed += (file_sizes[j] + cachedir_mp->fsp.f_bsize + 1) /
+ cachedir_mp->fsp.f_bsize;
+ }
+
+ if(check_mountpoint(handle, cachedir_mp)) {
+ error = 1;
+ }
+
+finish:
+ mount_point_list_free(mount_points);
+
+ if(error) {
+ RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1);
+ }
+
+ return 0;
+}
+
int _alpm_check_diskspace(alpm_handle_t *handle)
{
alpm_list_t *mount_points, *i;
@@ -300,32 +377,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..a613e232 100644
--- a/lib/libalpm/diskspace.h
+++ b/lib/libalpm/diskspace.h
@@ -50,6 +50,8 @@ typedef struct __alpm_mountpoint_t {
} alpm_mountpoint_t;
int _alpm_check_diskspace(alpm_handle_t *handle);
+int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir,
+ size_t num_files, off_t *file_sizes);
#endif /* _ALPM_DISKSPACE_H */
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index f5f2cd9c..9ab90b42 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -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/package.c b/lib/libalpm/package.c
index a5ff238f..0b0bf6e4 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -87,12 +87,12 @@ 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 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; }
@@ -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;
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index eff7d898..82a83264 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -27,7 +27,6 @@
#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,8 +43,8 @@
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 *);
@@ -89,8 +88,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;
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 44f3ee93..cf137ae8 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -239,8 +239,9 @@ static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file,
/* Helper function for iterating through a package's file and deleting them
* Used by _alpm_remove_commit. */
-static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
- const alpm_file_t *fileobj, alpm_list_t *skip_remove, int nosave)
+static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *oldpkg,
+ alpm_pkg_t *newpkg, const alpm_file_t *fileobj, alpm_list_t *skip_remove,
+ int nosave)
{
struct stat buf;
char file[PATH_MAX];
@@ -274,6 +275,10 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
} else if(files < 0) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"keeping directory %s (could not count files)\n", file);
+ } else if(newpkg && _alpm_filelist_contains(alpm_pkg_get_files(newpkg),
+ fileobj->name)) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "keeping directory %s (in new package)\n", file);
} else {
/* one last check- does any other package own this file? */
alpm_list_t *local, *local_pkgs;
@@ -285,7 +290,8 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *info,
/* we duplicated the package when we put it in the removal list, so we
* so we can't use direct pointer comparison here. */
- if(_alpm_pkg_cmp(info, local_pkg) == 0) {
+ if(oldpkg->name_hash == local_pkg->name_hash
+ && strcmp(oldpkg->name, local_pkg->name) == 0) {
continue;
}
filelist = alpm_pkg_get_files(local_pkg);
@@ -308,7 +314,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);
@@ -431,7 +437,7 @@ int _alpm_remove_single_package(alpm_handle_t *handle,
alpm_file_t *file = filelist->files + i - 1;
int percent;
/* TODO: check return code and handle accordingly */
- unlink_file(handle, oldpkg, file, skip_remove,
+ unlink_file(handle, oldpkg, newpkg, file, skip_remove,
handle->trans->flags & ALPM_TRANS_FLAG_NOSAVE);
if(!newpkg) {
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 54b9794a..52049a8c 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -686,11 +686,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 */
@@ -794,11 +794,92 @@ 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 != 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->download_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;
+
+ 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);
+ payload->handle = handle;
+ payload->allow_resume = 1;
+
+ if(_alpm_download(payload, cachedir, NULL) != -1) {
+ return 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);
@@ -817,91 +898,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->download_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;
- }
- }
- 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;
}
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 12286c6a..a60062bc 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -158,12 +158,10 @@ int _alpm_copyfile(const char *src, const char *dest)
}
}
- /* chmod dest to permissions of src, as long as it is not a symlink */
+ /* chmod dest to permissions of src */
struct stat statbuf;
- if(!stat(src, &statbuf)) {
- if(! S_ISLNK(statbuf.st_mode)) {
- fchmod(fileno(out), statbuf.st_mode);
- }
+ if(!fstat(fileno(in), &statbuf)) {
+ fchmod(fileno(out), statbuf.st_mode);
} else {
/* stat was unsuccessful */
ret = 1;
@@ -311,18 +309,11 @@ int _alpm_unpack(alpm_handle_t *handle, const char *archive, const char *prefix,
}
while(archive_read_next_header(_archive, &entry) == ARCHIVE_OK) {
- const struct stat *st;
- const char *entryname; /* the name of the file in the archive */
+ 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);
@@ -343,6 +334,13 @@ 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);
if(readret == ARCHIVE_WARN) {
@@ -553,6 +551,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *path, char *const argv[]
}
umask(0022);
execv(path, argv);
+ /* execv only returns if there was an error */
fprintf(stderr, _("call to execv failed (%s)\n"), strerror(errno));
exit(1);
} else {
@@ -914,16 +913,16 @@ int _alpm_test_checksum(const char *filepath, const char *expected,
/* Note: does NOT handle sparse files on purpose for speed. */
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 +932,20 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
b->ret = archive_read_data_block(a, (void *)&b->block,
&b->block_size, &offset);
b->block_offset = b->block;
+ block_remaining = b->block_size;
/* error, cleanup */
if(b->ret < ARCHIVE_OK) {
goto cleanup;
}
+ } else {
+ block_remaining = b->block + b->block_size - b->block_offset;
}
- /* loop through the block looking for EOL characters */
- for(i = b->block_offset; i < (b->block + b->block_size); i++) {
- /* check if read value was null or newline */
- if(*i == '\0' || *i == '\n') {
- done = 1;
- break;
- }
+ /* look through the block looking for EOL characters */
+ eol = memchr(b->block_offset, '\n', block_remaining);
+ if(!eol) {
+ eol = memchr(b->block_offset, '\0', block_remaining);
}
/* allocate our buffer, or ensure our existing one is big enough */
@@ -956,8 +955,10 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
b->line_size = b->block_size + 1;
b->line_offset = b->line;
} else {
- size_t needed = (size_t)((b->line_offset - b->line)
- + (i - b->block_offset) + 1);
+ /* note: we know eol > b->block_offset and b->line_offset > b->line,
+ * so we know the result is unsigned and can fit in size_t */
+ size_t new = eol ? (size_t)(eol - b->block_offset) : block_remaining;
+ size_t needed = (size_t)((b->line_offset - b->line) + new + 1);
if(needed > b->max_line_size) {
b->ret = -ERANGE;
goto cleanup;
@@ -974,11 +975,11 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
}
}
- if(done) {
- size_t len = (size_t)(i - b->block_offset);
+ if(eol) {
+ size_t len = (size_t)(eol - b->block_offset);
memcpy(b->line_offset, b->block_offset, len);
b->line_offset[len] = '\0';
- b->block_offset = ++i;
+ b->block_offset = eol + 1;
/* this is the main return point; from here you can read b->line */
return ARCHIVE_OK;
} else {
@@ -986,7 +987,7 @@ int _alpm_archive_fgets(struct archive *a, struct archive_read_buffer *b)
size_t len = (size_t)(b->block + b->block_size - b->block_offset);
memcpy(b->line_offset, b->block_offset, len);
b->line_offset += len;
- b->block_offset = i;
+ b->block_offset = b->block + b->block_size;
/* there was no new data, return what is left; saved ARCHIVE_EOF will be
* returned on next call */
if(len == 0) {
@@ -1103,8 +1104,12 @@ off_t _alpm_strtoofft(const char *line)
return (off_t)result;
}
-time_t _alpm_parsedate(const char *line)
+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,9 +1117,24 @@ 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);
}
- return (time_t)atol(line);
+
+ 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 (alpm_time_t)result;
}
/**
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 26fa9044..8d20a281 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -35,7 +35,6 @@
#include <string.h>
#include <stdarg.h>
#include <stddef.h> /* size_t */
-#include <time.h>
#include <sys/stat.h> /* struct stat */
#include <archive.h> /* struct archive */
#include <math.h> /* fabs */
@@ -51,7 +50,7 @@
#define ALLOC_FAIL(s) do { fprintf(stderr, "alloc failure: could not allocate %zd bytes\n", s); } while(0)
-#define MALLOC(p, s, action) do { p = calloc(1, s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0)
+#define MALLOC(p, s, action) do { p = malloc(s); if(p == NULL) { ALLOC_FAIL(s); action; } } while(0)
#define CALLOC(p, l, s, action) do { p = calloc(l, s); if(p == NULL) { ALLOC_FAIL(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)
@@ -127,7 +126,7 @@ 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);