[pacman-dev] [PATCH v7 1/2] Add configuration options for libcurl's "low speed" timeout
Christian Hesse
list at eworm.de
Mon Nov 14 08:32:45 UTC 2016
From: Christian Hesse <mail at eworm.de>
Add LowSpeedLimit and LowSpeedTime configuration options to correspond
to libcurl's CURLOPT_LOW_SPEED_LIMIT and CURLOPT_LOW_SPEED_TIME options.
This allows, e.g., transfers behind corporate virus-scanning firewalls
to survive the delays. Increasing the timeout may not be desirable in
all situations; similarly, disabling the check prevents detection of
disappearing networks.
Adds a utility function, parse_positive_long(), which yields a positive
(but not unsigned) long integer from a null-terminated string using
strtol(). A string containing anything but a base-10 number will cause
the function to return -1.
Original-Patch-by: Andrew Hills <ahills at ednos.net>
Signed-off-by: Christian Hesse <mail at eworm.de>
---
doc/pacman.conf.5.txt | 12 ++++++++++++
etc/pacman.conf.in | 4 ++++
lib/libalpm/alpm.h | 10 ++++++++++
lib/libalpm/dload.c | 4 ++--
lib/libalpm/handle.c | 32 ++++++++++++++++++++++++++++++++
lib/libalpm/handle.h | 9 +++++++++
src/pacman/conf.c | 24 ++++++++++++++++++++++++
src/pacman/conf.h | 4 ++++
src/pacman/util.c | 19 +++++++++++++++++++
src/pacman/util.h | 1 +
10 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index c665870..2346331 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -209,6 +209,18 @@ Options
Displays name, version and size of target packages formatted
as a table for upgrade, sync and remove operations.
+*LowSpeedLimit* = speed::
+ Sets the speed in bytes per second that a download should be below during
+ `LowSpeedTime` seconds to abort the transfer for being too slow. Setting
+ 'speed' to 0 will disable the speed check. Defaults to 1 byte per second.
+ Note that this option will not affect external programs specified by
+ `XferCommand`.
+
+*LowSpeedTime* = time::
+ Sets the time in seconds that a download should be below the `LowSpeedLimit`
+ transfer speed to abort the transfer for being too slow. Setting 'time' to
+ 0 will disable the speed check. Defaults to 10 seconds. Note that this
+ option will not affect external programs specified by `XferCommand`.
Repository Sections
-------------------
diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in
index 53071e5..ddc7397 100644
--- a/etc/pacman.conf.in
+++ b/etc/pacman.conf.in
@@ -29,6 +29,10 @@ Architecture = auto
#NoUpgrade =
#NoExtract =
+# Downloader options
+#LowSpeedLimit = 1
+#LowSpeedTime = 10
+
# Misc options
#UseSyslog
#Color
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 2d2491d..bea79da 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -812,6 +812,16 @@ const char *alpm_option_get_dbpath(alpm_handle_t *handle);
/** Get the name of the database lock file. Read-only. */
const char *alpm_option_get_lockfile(alpm_handle_t *handle);
+/** Returns the libcurl low speed limit in bytes per second. */
+long alpm_option_get_download_lowspeedlimit(alpm_handle_t *handle);
+/** Sets the libcurl low speed limit in bytes per second. */
+int alpm_option_set_download_lowspeedlimit(alpm_handle_t *handle, long lowspeedlimit);
+
+/** Returns the libcurl low speed time in seconds. */
+long alpm_option_get_download_lowspeedtime(alpm_handle_t *handle);
+/** Sets the libcurl low speed time in seconds. */
+int alpm_option_set_download_lowspeedtime(alpm_handle_t *handle, long lowspeedtime);
+
/** @name Accessors to the list of package cache directories.
* @{
*/
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 9d80358..c3bb200 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -305,8 +305,8 @@ static void curl_set_handle_opts(struct dload_payload *payload,
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, dload_progress_cb);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, (void *)payload);
- curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
- curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10L);
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, handle->download.lowspeedlimit);
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, handle->download.lowspeedtime);
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);
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 28e8148..6479798 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -247,6 +247,18 @@ const char SYMEXPORT *alpm_option_get_lockfile(alpm_handle_t *handle)
return handle->lockfile;
}
+long SYMEXPORT alpm_option_get_download_lowspeedlimit(alpm_handle_t *handle)
+{
+ CHECK_HANDLE(handle, return -1);
+ return handle->download.lowspeedlimit;
+}
+
+long SYMEXPORT alpm_option_get_download_lowspeedtime(alpm_handle_t *handle)
+{
+ CHECK_HANDLE(handle, return -1);
+ return handle->download.lowspeedtime;
+}
+
const char SYMEXPORT *alpm_option_get_gpgdir(alpm_handle_t *handle)
{
CHECK_HANDLE(handle, return NULL);
@@ -362,6 +374,26 @@ int SYMEXPORT alpm_option_set_progresscb(alpm_handle_t *handle, alpm_cb_progress
return 0;
}
+int SYMEXPORT alpm_option_set_download_lowspeedlimit(alpm_handle_t *handle, long lowspeedlimit)
+{
+ CHECK_HANDLE(handle, return -1);
+ if(lowspeedlimit < 0) {
+ RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+ }
+ handle->download.lowspeedlimit = lowspeedlimit;
+ return 0;
+}
+
+int SYMEXPORT alpm_option_set_download_lowspeedtime(alpm_handle_t *handle, long lowspeedtime)
+{
+ CHECK_HANDLE(handle, return -1);
+ if(lowspeedtime < 0) {
+ RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+ }
+ handle->download.lowspeedtime = lowspeedtime;
+ return 0;
+}
+
static char *canonicalize_path(const char *path)
{
char *new_path;
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 652f17d..0c66469 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -50,6 +50,14 @@ do { \
} \
} while(0)
+#ifdef HAVE_LIBCURL
+struct download {
+ /* Curl timeouts */
+ long lowspeedlimit;
+ long lowspeedtime;
+};
+#endif
+
struct __alpm_handle_t {
/* internal usage */
alpm_db_t *db_local; /* local db pointer */
@@ -60,6 +68,7 @@ struct __alpm_handle_t {
#ifdef HAVE_LIBCURL
/* libcurl handle */
CURL *curl; /* reusable curl_easy handle */
+ struct download download;
#endif
#ifdef HAVE_LIBGPGME
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index d8d64fb..520f4d0 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -122,6 +122,9 @@ config_t *config_new(void)
newconfig->colstr.err = "";
newconfig->colstr.nocolor = "";
+ newconfig->lowspeedlimit = 1L;
+ newconfig->lowspeedtime = 10L;
+
return newconfig;
}
@@ -603,6 +606,24 @@ static int _parse_options(const char *key, char *value,
return 1;
}
FREELIST(values);
+ } else if(strcmp(key, "LowSpeedLimit") == 0) {
+ config->lowspeedlimit = parse_positive_long(value);
+ if(config->lowspeedlimit < 0) {
+ pm_printf(ALPM_LOG_WARNING,
+ _("config file %s, line %d: invalid %s, using default.\n"),
+ file, linenum, "LowSpeedLimit");
+ config->lowspeedlimit = 1L;
+ }
+ pm_printf(ALPM_LOG_DEBUG, "config: lowspeedlimit: %ld\n", config->lowspeedlimit);
+ } else if(strcmp(key, "LowSpeedTime") == 0) {
+ config->lowspeedtime = parse_positive_long(value);
+ if(config->lowspeedtime < 0) {
+ pm_printf(ALPM_LOG_WARNING,
+ _("config file %s, line %d: invalid %s, using default.\n"),
+ file, linenum, "LowSpeedTime");
+ config->lowspeedtime = 10L;
+ }
+ pm_printf(ALPM_LOG_DEBUG, "config: lowspeedtime: %ld\n", config->lowspeedtime);
} else {
pm_printf(ALPM_LOG_WARNING,
_("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
@@ -733,6 +754,9 @@ static int setup_libalpm(void)
alpm_option_set_questioncb(handle, cb_question);
alpm_option_set_progresscb(handle, cb_progress);
+ alpm_option_set_download_lowspeedlimit(handle, config->lowspeedlimit);
+ alpm_option_set_download_lowspeedtime(handle, config->lowspeedtime);
+
if(config->op == PM_OP_FILES) {
alpm_option_set_dbext(handle, ".files");
}
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 945de7c..17e5f27 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -133,6 +133,10 @@ typedef struct __config_t {
/* Color strings for output */
colstr_t colstr;
+ /* Curl timeouts */
+ long lowspeedlimit;
+ long lowspeedtime;
+
alpm_list_t *repos;
} config_t;
diff --git a/src/pacman/util.c b/src/pacman/util.c
index fd7438b..bd85d8a 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1620,6 +1620,25 @@ int noyes(const char *format, ...)
return ret;
}
+/* Attempts to extract a positive long from a string; failure yields -1. */
+long parse_positive_long(const char *str)
+{
+ char *end;
+ long num;
+
+ errno = 0;
+ num = strtol(str, &end, 10);
+
+ if(end == str || /* Not a decimal number */
+ *end != 0 || /* Extra characters */
+ (num == LONG_MAX && errno == ERANGE) || /* Out of range */
+ num < 0) { /* Out of range (negative) */
+ return -1;
+ }
+
+ return num;
+}
+
int colon_printf(const char *fmt, ...)
{
int ret;
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 0a6ce97..fa84ecc 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -76,6 +76,7 @@ int multiselect_question(char *array, int count);
int colon_printf(const char *format, ...) __attribute__((format(printf, 1, 2)));
int yesno(const char *format, ...) __attribute__((format(printf, 1, 2)));
int noyes(const char *format, ...) __attribute__((format(printf, 1, 2)));
+long parse_positive_long(const char *str);
int pm_printf(alpm_loglevel_t level, const char *format, ...) __attribute__((format(printf,2,3)));
int pm_asprintf(char **string, const char *format, ...) __attribute__((format(printf,2,3)));
--
2.10.2
More information about the pacman-dev
mailing list