summaryrefslogtreecommitdiffstats
path: root/lib/libalpm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm')
-rw-r--r--lib/libalpm/diskspace.c56
-rw-r--r--lib/libalpm/dload.c155
-rw-r--r--lib/libalpm/remove.c2
-rw-r--r--lib/libalpm/signing.c2
-rw-r--r--lib/libalpm/util.c10
5 files changed, 176 insertions, 49 deletions
diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c
index 274aa676..91b655e5 100644
--- a/lib/libalpm/diskspace.c
+++ b/lib/libalpm/diskspace.c
@@ -1,7 +1,7 @@
/*
* diskspace.c
*
- * 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
@@ -17,10 +17,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "config.h"
+
+#include <stdio.h>
#include <errno.h>
+
#if defined(HAVE_MNTENT_H)
#include <mntent.h>
#endif
+#if defined(HAVE_SYS_MNTTAB_H)
+#include <sys/mnttab.h>
+#endif
#if defined(HAVE_SYS_STATVFS_H)
#include <sys/statvfs.h>
#endif
@@ -69,10 +76,10 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
alpm_list_t *mount_points = NULL, *ptr;
alpm_mountpoint_t *mp;
-#if defined HAVE_GETMNTENT
+#if defined(HAVE_GETMNTENT) && defined(HAVE_MNTENT_H)
+ /* Linux */
struct mntent *mnt;
FILE *fp;
- struct statvfs fsp;
fp = setmntent(MOUNTED, "r");
@@ -81,8 +88,10 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
}
while((mnt = getmntent(fp))) {
+ struct statvfs fsp;
if(!mnt) {
- _alpm_log(handle, ALPM_LOG_WARNING, _("could not get filesystem information\n"));
+ _alpm_log(handle, ALPM_LOG_WARNING,
+ _("could not get filesystem information\n"));
continue;
}
if(statvfs(mnt->mnt_dir, &fsp) != 0) {
@@ -102,7 +111,44 @@ static alpm_list_t *mount_point_list(alpm_handle_t *handle)
}
endmntent(fp);
-#elif defined HAVE_GETMNTINFO
+#elif defined(HAVE_GETMNTENT) && defined(HAVE_MNTTAB_H)
+ /* Solaris, Illumos */
+ struct mnttab mnt;
+ FILE *fp;
+ int ret;
+
+ fp = fopen("/etc/mnttab", "r");
+
+ if(fp == NULL) {
+ 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);
+ }
+ /* -1 == EOF */
+ if(ret != -1) {
+ _alpm_log(handle, ALPM_LOG_WARNING,
+ _("could not get filesystem information\n"));
+ }
+
+ fclose(fp);
+#elif defined(HAVE_GETMNTINFO)
+ /* FreeBSD (statfs), NetBSD (statvfs), OpenBSD (statfs), OS X (statfs) */
int entries;
FSSTATSTYPE *fsp;
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index a3980d65..97778c27 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -1,7 +1,7 @@
/*
* download.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
@@ -23,11 +23,19 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#include <sys/socket.h> /* setsockopt, SO_KEEPALIVE */
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h> /* IPPROTO_TCP */
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h> /* TCP_KEEPINTVL, TCP_KEEPIDLE */
+#endif
+
#ifdef HAVE_LIBCURL
#include <curl/curl.h>
#endif
@@ -82,7 +90,7 @@ static void inthandler(int UNUSED signum)
dload_interrupted = ABORT_SIGINT;
}
-static int curl_progress(void *file, double dltotal, double dlnow,
+static int dload_progress_cb(void *file, double dltotal, double dlnow,
double UNUSED ultotal, double UNUSED ulnow)
{
struct dload_payload *payload = (struct dload_payload *)file;
@@ -184,7 +192,7 @@ static mode_t _getumask(void)
return mask;
}
-static size_t parse_headers(void *ptr, size_t size, size_t nmemb, void *user)
+static size_t dload_parseheader_cb(void *ptr, size_t size, size_t nmemb, void *user)
{
size_t realsize = size * nmemb;
const char *fptr, *endptr = NULL;
@@ -215,6 +223,47 @@ static size_t parse_headers(void *ptr, size_t size, size_t nmemb, void *user)
return realsize;
}
+static int dload_sockopt_cb(void *userdata, curl_socket_t curlfd,
+ curlsocktype purpose)
+{
+ alpm_handle_t *handle = userdata;
+ int optval = 1;
+
+ /* this whole method is to prevent FTP control connections from going sour
+ * during a long data transfer; crappy firewalls love to drop otherwise idle
+ * connections if there is no traffic. */
+ if(purpose != CURLSOCKTYPE_IPCXN) {
+ return 0;
+ }
+
+ /* don't abort operation if any setsockopt fails, just log to debug */
+ if(setsockopt(curlfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval,
+ sizeof(optval)) < 0) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "Failed to set SO_KEEPALIVE on fd %d\n", curlfd);
+ }
+ else {
+#ifdef TCP_KEEPIDLE
+ optval = 60;
+ if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&optval,
+ sizeof(optval)) < 0) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "Failed to set TCP_KEEPIDLE on fd %d\n", curlfd);
+ }
+#endif
+#ifdef TCP_KEEPINTVL
+ optval = 60;
+ if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&optval,
+ sizeof(optval)) < 0) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "Failed to set TCP_KEEPINTVL on fd %d\n", curlfd);
+ }
+#endif
+ }
+
+ return 0;
+}
+
static void curl_set_handle_opts(struct dload_payload *payload,
CURL *curl, char *error_buffer)
{
@@ -232,13 +281,15 @@ static void curl_set_handle_opts(struct dload_payload *payload,
curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
- curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curl_progress);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, dload_progress_cb);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, (void *)payload);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1024L);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10L);
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_headers);
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, dload_parseheader_cb);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)payload);
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, dload_sockopt_cb);
+ curl_easy_setopt(curl, CURLOPT_SOCKOPTDATA, (void *)handle);
_alpm_log(handle, ALPM_LOG_DEBUG, "url: %s\n", payload->fileurl);
@@ -388,6 +439,8 @@ static int curl_download_internal(struct dload_payload *payload,
/* perform transfer */
payload->curlerr = curl_easy_perform(curl);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "curl returned error %d from transfer\n",
+ payload->curlerr);
/* disconnect relationships from the curl handle for things that might go out
* of scope, but could still be touched on connection teardown. This really
@@ -558,6 +611,22 @@ 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, '/');
+
+ if(basename == NULL) {
+ return NULL;
+ }
+
+ basename++;
+ if(basename == '\0') {
+ return NULL;
+ }
+
+ return _alpm_filecache_find(handle, basename);
+}
+
/** Fetch a remote pkg. */
char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, const char *url)
{
@@ -565,7 +634,7 @@ char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, const char *url)
const char *cachedir;
char *final_file = NULL;
struct dload_payload payload;
- int ret;
+ int ret = 0;
CHECK_HANDLE(handle, return NULL);
ASSERT(url, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL));
@@ -574,51 +643,63 @@ char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, const char *url)
cachedir = _alpm_filecache_setup(handle);
memset(&payload, 0, sizeof(struct dload_payload));
- payload.handle = handle;
- STRDUP(payload.fileurl, url, RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
- payload.allow_resume = 1;
-
- /* download the file */
- ret = _alpm_download(&payload, cachedir, &final_file);
- _alpm_dload_payload_reset(&payload);
- if(ret == -1) {
- _alpm_log(handle, ALPM_LOG_WARNING, _("failed to download %s\n"), url);
- free(final_file);
- return NULL;
+
+ /* attempt to find the file in our pkgcache */
+ filepath = filecache_find_url(handle, url);
+ if(filepath == NULL) {
+ STRDUP(payload.fileurl, url, RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
+ payload.allow_resume = 1;
+ payload.handle = handle;
+
+ /* download the file */
+ ret = _alpm_download(&payload, cachedir, &final_file);
+ _alpm_dload_payload_reset(&payload);
+ if(ret == -1) {
+ _alpm_log(handle, ALPM_LOG_WARNING, _("failed to download %s\n"), url);
+ free(final_file);
+ return NULL;
+ }
+ _alpm_log(handle, ALPM_LOG_DEBUG, "successfully downloaded %s\n", url);
}
- _alpm_log(handle, ALPM_LOG_DEBUG, "successfully downloaded %s\n", url);
/* attempt to download the signature */
if(ret == 0 && (handle->siglevel & ALPM_SIG_PACKAGE)) {
- char *sig_final_file = NULL;
+ char *sig_filepath, *sig_final_file = NULL;
size_t len;
len = strlen(url) + 5;
MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
snprintf(payload.fileurl, len, "%s.sig", url);
- payload.handle = handle;
- payload.force = 1;
- payload.errors_ok = (handle->siglevel & ALPM_SIG_PACKAGE_OPTIONAL);
-
- /* set hard upper limit of 16KiB */
- payload.max_size = 16 * 1024;
-
- ret = _alpm_download(&payload, cachedir, &sig_final_file);
- if(ret == -1 && !payload.errors_ok) {
- _alpm_log(handle, ALPM_LOG_WARNING,
- _("failed to download %s\n"), payload.fileurl);
- /* Warn now, but don't return NULL. We will fail later during package
- * load time. */
- } else if(ret == 0) {
- _alpm_log(handle, ALPM_LOG_DEBUG,
- "successfully downloaded %s\n", payload.fileurl);
+
+ sig_filepath = filecache_find_url(handle, payload.fileurl);
+ if(sig_filepath == NULL) {
+ payload.handle = handle;
+ payload.force = 1;
+ payload.errors_ok = (handle->siglevel & ALPM_SIG_PACKAGE_OPTIONAL);
+
+ /* set hard upper limit of 16KiB */
+ payload.max_size = 16 * 1024;
+
+ ret = _alpm_download(&payload, cachedir, &sig_final_file);
+ if(ret == -1 && !payload.errors_ok) {
+ _alpm_log(handle, ALPM_LOG_WARNING,
+ _("failed to download %s\n"), payload.fileurl);
+ /* Warn now, but don't return NULL. We will fail later during package
+ * load time. */
+ } else if(ret == 0) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "successfully downloaded %s\n", payload.fileurl);
+ }
+ FREE(sig_final_file);
}
- FREE(sig_final_file);
+ free(sig_filepath);
_alpm_dload_payload_reset(&payload);
}
/* we should be able to find the file the second time around */
- filepath = _alpm_filecache_find(handle, final_file);
+ if(filepath == NULL) {
+ filepath = _alpm_filecache_find(handle, final_file);
+ }
free(final_file);
return filepath;
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index bc196510..469ce9bb 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -1,7 +1,7 @@
/*
* remove.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c
index 3ff83ba0..cfe0f5e8 100644
--- a/lib/libalpm/signing.c
+++ b/lib/libalpm/signing.c
@@ -1,7 +1,7 @@
/*
* signing.c
*
- * 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/util.c b/lib/libalpm/util.c
index e2cbd8c5..3cc4bbf7 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -1,7 +1,7 @@
/*
* util.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>
@@ -406,7 +406,6 @@ int _alpm_rmrf(const char *path)
int errflag = 0;
struct dirent *dp;
DIR *dirp;
- char name[PATH_MAX];
struct stat st;
if(_alpm_lstat(path, &st) == 0) {
@@ -426,9 +425,10 @@ int _alpm_rmrf(const char *path)
return 1;
}
for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- if(dp->d_ino) {
- sprintf(name, "%s/%s", path, dp->d_name);
+ 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);
}
}
@@ -1168,7 +1168,7 @@ off_t _alpm_strtoofft(const char *line)
errno = 0;
/* we are trying to parse bare numbers only, no leading anything */
- if(line[0] < '0' || line[0] > '9') {
+ if(!isdigit((unsigned char)line[0])) {
return (off_t)-1;
}
result = strtoull(line, &end, 10);