[pacman-dev] [PATCH] Add option MaxDlSpeed to limit download speed
Olivier Brunel
jjk at jjacky.com
Fri Aug 19 18:12:44 UTC 2016
Signed-off-by: Olivier Brunel <jjk at jjacky.com>
---
doc/pacman.8.txt | 5 +++++
doc/pacman.conf.5.txt | 6 ++++++
lib/libalpm/alpm.h | 3 +++
lib/libalpm/dload.c | 1 +
lib/libalpm/handle.c | 26 ++++++++++++++++++++++++++
lib/libalpm/handle.h | 1 +
src/pacman/conf.c | 11 +++++++++++
src/pacman/conf.h | 4 +++-
src/pacman/pacman.c | 11 +++++++++++
src/pacman/util.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
src/pacman/util.h | 2 ++
11 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index 231e0bc..1890cd9 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -266,6 +266,11 @@ Upgrade Options (apply to '-S' and '-U')[[UO]]
*\--needed*::
Do not reinstall the targets that are already up-to-date.
+*\--maxdlspeed* <speed>::
+ Sets the maximum download speed to the specified speed in bytes/s, unless a
+ suffix is appended. Suffix 'k' or 'K' will count as KiB/s, 'm' or 'M' as
+ MiB/s, and 'g' or 'G' as GiB/s.
+
Query Options (apply to '-Q')[[QO]]
-----------------------------------
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index c665870..49ce63b 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -201,6 +201,12 @@ Options
bar is still based solely on the current file download.
This option won't work if XferCommand is used.
+*MaxDlSpeed*::
+ Sets the maximum download speed to the specified speed in bytes/s, unless a
+ suffix is appended. Suffix 'k' or 'K' will count as KiB/s, 'm' or 'M' as
+ MiB/s, and 'g' or 'G' as GiB/s.
+ This option won't work if XferCommand is used.
+
*CheckSpace*::
Performs an approximate check for adequate available disk space before
installing packages.
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 168d71b..7e4e9da 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -925,6 +925,9 @@ int alpm_option_set_local_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t l
alpm_siglevel_t alpm_option_get_remote_file_siglevel(alpm_handle_t *handle);
int alpm_option_set_remote_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t level);
+off_t alpm_option_get_maxdlspeed(alpm_handle_t *handle);
+int alpm_option_set_maxdlspeed(alpm_handle_t *handle, off_t speed);
+
/** @} */
/** @addtogroup alpm_api_databases Database Functions
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 31ae82c..8c6d6af 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -295,6 +295,7 @@ static void curl_set_handle_opts(struct dload_payload *payload,
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, dload_progress_cb);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, (void *)payload);
+ curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, handle->maxdlspeed);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10L);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, dload_parseheader_cb);
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index e9439a0..9cab5da 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -844,4 +844,30 @@ alpm_siglevel_t SYMEXPORT alpm_option_get_remote_file_siglevel(alpm_handle_t *ha
}
}
+off_t SYMEXPORT alpm_option_get_maxdlspeed(alpm_handle_t *handle)
+{
+ CHECK_HANDLE(handle, return -1);
+#ifdef HAVE_LIBCURL
+ return (off_t) handle->maxdlspeed;
+#else
+ return 0;
+#endif
+}
+
+int SYMEXPORT alpm_option_set_maxdlspeed(alpm_handle_t *handle, off_t speed)
+{
+ CHECK_HANDLE(handle, return -1);
+#ifdef HAVE_LIBCURL
+ if(speed >= 0) {
+ handle->maxdlspeed = (curl_off_t) speed;
+ return 0;
+ } else
+#else
+ if(speed == 0)
+ return 0;
+ else
+#endif
+ RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+}
+
/* vim: set noet: */
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index a1d0f9a..f55b6ed 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -60,6 +60,7 @@ struct __alpm_handle_t {
#ifdef HAVE_LIBCURL
/* libcurl handle */
CURL *curl; /* reusable curl_easy handle */
+ curl_off_t maxdlspeed; /* maximum download speed (B/s) */
#endif
#ifdef HAVE_LIBGPGME
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 25de7af..39cc15c 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -544,6 +544,16 @@ static int _parse_options(const char *key, char *value,
}
config->deltaratio = ratio;
pm_printf(ALPM_LOG_DEBUG, "config: usedelta = %f\n", ratio);
+ } else if(strcmp(key, "MaxDlSpeed") == 0) {
+ off_t speed = parsesize(value);
+ if(speed < 0) {
+ pm_printf(ALPM_LOG_ERROR,
+ _("config file %s, line %d: invalid value for '%s' : '%s'\n"),
+ file, linenum, "MaxDlSpeed", value);
+ return 1;
+ }
+ config->maxdlspeed = speed;
+ pm_printf(ALPM_LOG_DEBUG, "config: maxdlspeed = %jd\n", (intmax_t) speed);
} else if(strcmp(key, "DBPath") == 0) {
/* don't overwrite a path specified on the command line */
if(!config->dbpath) {
@@ -810,6 +820,7 @@ static int setup_libalpm(void)
alpm_option_set_checkspace(handle, config->checkspace);
alpm_option_set_usesyslog(handle, config->usesyslog);
alpm_option_set_deltaratio(handle, config->deltaratio);
+ alpm_option_set_maxdlspeed(handle, config->maxdlspeed);
alpm_option_set_ignorepkgs(handle, config->ignorepkg);
alpm_option_set_ignoregroups(handle, config->ignoregrp);
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 2aba8bf..77353a2 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -56,6 +56,7 @@ typedef struct __config_t {
unsigned short usesyslog;
unsigned short color;
double deltaratio;
+ off_t maxdlspeed;
char *arch;
char *print_format;
/* unfortunately, we have to keep track of paths both here and in the library
@@ -201,7 +202,8 @@ enum {
OP_VERBOSE,
OP_DOWNLOADONLY,
OP_REFRESH,
- OP_ASSUMEINSTALLED
+ OP_ASSUMEINSTALLED,
+ OP_MAXDLSPEED
};
/* clean method */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index be52d1b..91f8500 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -194,6 +194,8 @@ static void usage(int op, const char * const myname)
addlist(_(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n"));
addlist(_(" --ignoregroup <grp>\n"
" ignore a group upgrade (can be used more than once)\n"));
+ addlist(_(" --maxdlspeed <speed>\n"
+ " set the maximum download speed\n"));
/* pass through */
case PM_OP_REMOVE:
addlist(_(" -d, --nodeps skip dependency version checks (-dd to skip all checks)\n"));
@@ -713,6 +715,14 @@ static int parsearg_upgrade(int opt)
case OP_IGNOREGROUP:
parsearg_util_addlist(&(config->ignoregrp));
break;
+ case OP_MAXDLSPEED:
+ {
+ off_t speed = parsesize(optarg);
+ if(speed < 0)
+ return 1;
+ config->maxdlspeed = speed;
+ break;
+ }
default: return 1;
}
return 0;
@@ -929,6 +939,7 @@ static int parseargs(int argc, char *argv[])
{"ignoregroup", required_argument, 0, OP_IGNOREGROUP},
{"needed", no_argument, 0, OP_NEEDED},
{"asexplicit", no_argument, 0, OP_ASEXPLICIT},
+ {"maxdlspeed", required_argument, 0, OP_MAXDLSPEED},
{"arch", required_argument, 0, OP_ARCH},
{"print-format", required_argument, 0, OP_PRINTFORMAT},
{"gpgdir", required_argument, 0, OP_GPGDIR},
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 81780f7..35b4f23 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1763,4 +1763,49 @@ int pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list
return ret;
}
+off_t parsesize(const char *str)
+{
+ long size;
+ char *endptr;
+
+ size = strtol(str, &endptr, 10);
+ if((size == LONG_MIN || size == LONG_MAX) && errno == ERANGE) {
+ return -1;
+ }
+ if(*endptr != '\0') {
+ if(endptr[1] != '\0') {
+ return -1;
+ }
+ switch(*endptr) {
+ case 'g':
+ case 'G':
+ if(size > LONG_MAX / 1024) {
+ return -1;
+ }
+ size *= 1024;
+ /* fallthrough */
+ case 'm':
+ case 'M':
+ if(size > LONG_MAX / 1024) {
+ return -1;
+ }
+ size *= 1024;
+ /* fallthrough */
+ case 'k':
+ case 'K':
+ if(size > LONG_MAX / 1024) {
+ return -1;
+ }
+ size *= 1024;
+ break;
+ default:
+ return -1;
+ }
+ }
+ if(size < 0) {
+ return -1;
+ }
+ return (off_t) size;
+}
+
/* vim: set noet: */
diff --git a/src/pacman/util.h b/src/pacman/util.h
index f5e37c8..7d0a897 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -82,6 +82,8 @@ int pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list
int pm_sprintf(char **string, alpm_loglevel_t level, const char *format, ...) __attribute__((format(printf,3,4)));
int pm_vasprintf(char **string, alpm_loglevel_t level, const char *format, va_list args) __attribute__((format(printf,3,0)));
+off_t parsesize(const char *str);
+
#endif /* _PM_UTIL_H */
/* vim: set noet: */
--
2.9.3
More information about the pacman-dev
mailing list