From b426488e2b1cf4e464f7f56dbcf2629a3a73a54a Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 18 Jan 2012 15:32:48 -0600 Subject: Use isdigit() rather than character range comparisons This is safer and guaranteed to work with even exotic character sets. Signed-off-by: Dan McGee --- lib/libalpm/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index ad15d937..2d0153e5 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -1085,7 +1085,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); -- cgit v1.2.3 From 4e60b9646d69227c6c9f226bf03a12158feaaee7 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Sat, 14 Jan 2012 15:27:48 -0500 Subject: fetch_url: look for files in cache before downloading We lost this logic somewhere between the libfetch and libcurl transition, as it existed in the internal downloader, but was pulled back only into the sync workflow. Add a helper function that will let us check for existance in the filecache prior to calling the downloader. Signed-off-by: Dave Reisner Signed-off-by: Dan McGee --- lib/libalpm/dload.c | 92 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 32 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 29285903..928324e8 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -562,6 +562,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) { @@ -569,7 +585,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)); @@ -578,51 +594,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; -- cgit v1.2.3 From 1b50223f8240456b8c989b5c1e016f4a245b527c Mon Sep 17 00:00:00 2001 From: Olivier Brunel Date: Mon, 9 Jan 2012 21:37:31 +0100 Subject: util.c, rmrf(): only create string when needed The entry's name is only used when not "." or ".." so only print the string then. Signed-off-by: Olivier Brunel Signed-off-by: Dan McGee --- lib/libalpm/util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 2d0153e5..6834751f 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -381,7 +381,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) { @@ -401,9 +400,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); } } -- cgit v1.2.3 From 562109c0e8717eaac3b9078271c4ca4f82abfecd Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 18 Jan 2012 22:25:27 -0600 Subject: Update copyright on changed files since beginning of year Signed-off-by: Dan McGee --- lib/libalpm/dload.c | 2 +- lib/libalpm/remove.c | 2 +- lib/libalpm/signing.c | 2 +- lib/libalpm/util.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 928324e8..6fe4a323 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -1,7 +1,7 @@ /* * download.c * - * Copyright (c) 2006-2011 Pacman Development Team + * Copyright (c) 2006-2012 Pacman Development Team * Copyright (c) 2002-2006 by Judd Vinet * * This program is free software; you can redistribute it and/or modify diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 41cee514..cc9e289d 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -1,7 +1,7 @@ /* * remove.c * - * Copyright (c) 2006-2011 Pacman Development Team + * Copyright (c) 2006-2012 Pacman Development Team * Copyright (c) 2002-2006 by Judd Vinet * Copyright (c) 2005 by Aurelien Foret * Copyright (c) 2005 by Christian Hamar diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c index 1a53deaa..3ec957de 100644 --- a/lib/libalpm/signing.c +++ b/lib/libalpm/signing.c @@ -1,7 +1,7 @@ /* * signing.c * - * Copyright (c) 2008-2011 Pacman Development Team + * Copyright (c) 2008-2012 Pacman Development Team * * 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 6834751f..0e5e8a00 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -1,7 +1,7 @@ /* * util.c * - * Copyright (c) 2006-2011 Pacman Development Team + * Copyright (c) 2006-2012 Pacman Development Team * Copyright (c) 2002-2006 by Judd Vinet * Copyright (c) 2005 by Aurelien Foret * Copyright (c) 2005 by Christian Hamar -- cgit v1.2.3 From 1eb40c83287b07ac7428ad2d58504f386fad98f1 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 19 Jan 2012 16:21:06 -0600 Subject: Add diskspace checking support for Solaris/Illumos Was able to get my hands on one of these boxes today, so add yet another new way of doing this. I'm glad these calls are so standardized. This was compile tested on Linux and Illumos and seems to still be working in both places. Signed-off-by: Dan McGee --- lib/libalpm/diskspace.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index fe2036d5..4127153d 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -1,7 +1,7 @@ /* * diskspace.c * - * Copyright (c) 2010-2011 Pacman Development Team + * Copyright (c) 2010-2012 Pacman Development Team * * 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,10 +19,15 @@ #include "config.h" +#include #include + #if defined(HAVE_MNTENT_H) #include #endif +#if defined(HAVE_MNTTAB_H) +#include +#endif #if defined(HAVE_SYS_STATVFS_H) #include #endif @@ -60,10 +65,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"); @@ -72,8 +77,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) { @@ -93,7 +100,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; -- cgit v1.2.3 From 44f146f232be5203fb01ad35fdf73122838df97c Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Sat, 21 Jan 2012 21:31:39 -0500 Subject: lib/dload: enforce usage of TCP keepalives This is particularly important in the case of FTP control connections, which may be closed by rogue NAT/firewall devices detecting idle connections on larger transfers which may take 5-10+ minutes. Signed-off-by: Dave Reisner Signed-off-by: Dan McGee --- lib/libalpm/dload.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'lib') diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 6fe4a323..f5af7c64 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -25,11 +25,19 @@ #include #include #include +#include /* setsockopt, SO_KEEPALIVE */ #include #include #include #include +#ifdef HAVE_NETINET_IN_H +#include /* IPPROTO_TCP */ +#endif +#ifdef HAVE_NETINET_TCP_H +#include /* TCP_KEEPINTVL, TCP_KEEPIDLE */ +#endif + #ifdef HAVE_LIBCURL #include #endif @@ -217,6 +225,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) { @@ -241,6 +290,8 @@ static void curl_set_handle_opts(struct dload_payload *payload, curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_headers); 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); @@ -392,6 +443,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 -- cgit v1.2.3 From a03c35125ec729b914600b7c24084f83a05a5ede Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 23 Jan 2012 12:15:53 -0600 Subject: Fix sys/mnttab.h header include Signed-off-by: Dan McGee --- lib/libalpm/diskspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 4127153d..d0f52a63 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -25,8 +25,8 @@ #if defined(HAVE_MNTENT_H) #include #endif -#if defined(HAVE_MNTTAB_H) -#include +#if defined(HAVE_SYS_MNTTAB_H) +#include #endif #if defined(HAVE_SYS_STATVFS_H) #include -- cgit v1.2.3 From 825b4ff35aa676b139dc24bc651724b092f2fded Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Sun, 22 Jan 2012 18:46:23 -0500 Subject: lib/dload: give uniform naming to curl CB functions Signed-off-by: Dave Reisner Signed-off-by: Dan McGee --- lib/libalpm/dload.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index f5af7c64..414d5d76 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -92,7 +92,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; @@ -194,7 +194,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; @@ -283,11 +283,11 @@ 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); -- cgit v1.2.3