diff options
author | Dan McGee <dan@archlinux.org> | 2012-01-23 12:19:51 -0600 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2012-01-23 12:20:52 -0600 |
commit | e50c4a8837cedf47c2fe1a2c6064b4dc03dc5b03 (patch) | |
tree | df2e33d95d02b17e5d720320c19e267893d68bdf /lib/libalpm | |
parent | b3612e9cc198f198b3806efa461bf6fc04dd4502 (diff) | |
parent | 825b4ff35aa676b139dc24bc651724b092f2fded (diff) | |
download | pacman-e50c4a8837cedf47c2fe1a2c6064b4dc03dc5b03.tar.xz |
Merge branch 'maint'
Conflicts:
lib/libalpm/diskspace.c
src/pacman/util.h
Diffstat (limited to 'lib/libalpm')
-rw-r--r-- | lib/libalpm/diskspace.c | 56 | ||||
-rw-r--r-- | lib/libalpm/dload.c | 155 | ||||
-rw-r--r-- | lib/libalpm/remove.c | 2 | ||||
-rw-r--r-- | lib/libalpm/signing.c | 2 | ||||
-rw-r--r-- | lib/libalpm/util.c | 10 |
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); |