aboutsummaryrefslogtreecommitdiffstats
path: root/g10/progress.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/progress.c')
-rw-r--r--g10/progress.c60
1 files changed, 45 insertions, 15 deletions
diff --git a/g10/progress.c b/g10/progress.c
index 21810a45b..a1027b8d3 100644
--- a/g10/progress.c
+++ b/g10/progress.c
@@ -71,6 +71,49 @@ release_progress_context (progress_filter_context_t *pfx)
}
+static void
+write_status_progress (const char *what,
+ unsigned long current, unsigned long total)
+{
+ char buffer[50];
+
+ /* Although we use an unsigned long for the values, 32 bit
+ * applications using GPGME will use an "int" and thus are limited
+ * in the total size which can be represented. On Windows, where
+ * sizeof(int)==sizeof(long), this is even worse and will lead to an
+ * integer overflow for all files larger than 2 GiB. Although, the
+ * allowed value range of TOTAL and CURRENT is nowhere specified, we
+ * better protect applications from the need to handle negative
+ * values. The common usage pattern of the progress information is
+ * to display how many percent of the operation has been done and
+ * thus scaling CURRENT and TOTAL down before they get to large,
+ * should not have a noticeable effect except for rounding
+ * imprecision. */
+ if (total)
+ {
+ if (current > total)
+ current = total;
+
+ while (total > 1024*1024)
+ {
+ total /= 1024;
+ current /= 1024;
+ }
+ }
+ else
+ {
+ while (current > 1024*1024)
+ {
+ current /= 1024;
+ }
+ }
+
+ snprintf (buffer, sizeof buffer, "%.20s ? %lu %lu",
+ what? what : "?", current, total);
+ write_status_text (STATUS_PROGRESS, buffer);
+}
+
+
/****************
* The filter is used to report progress to the user.
*/
@@ -83,17 +126,11 @@ progress_filter (void *opaque, int control,
if (control == IOBUFCTRL_INIT)
{
- char buffer[50];
-
pfx->last = 0;
pfx->offset = 0;
pfx->last_time = make_timestamp ();
- sprintf (buffer, "%.20s ? %lu %lu",
- pfx->what? pfx->what : "?",
- pfx->offset,
- pfx->total);
- write_status_text (STATUS_PROGRESS, buffer);
+ write_status_progress (pfx->what, pfx->offset, pfx->total);
}
else if (control == IOBUFCTRL_UNDERFLOW)
{
@@ -113,14 +150,7 @@ progress_filter (void *opaque, int control,
if ((len == -1 && pfx->offset != pfx->last)
|| timestamp - pfx->last_time > 0)
{
- char buffer[50];
-
- sprintf (buffer, "%.20s ? %lu %lu",
- pfx->what? pfx->what : "?",
- pfx->offset,
- pfx->total);
- write_status_text (STATUS_PROGRESS, buffer);
-
+ write_status_progress (pfx->what, pfx->offset, pfx->total);
pfx->last = pfx->offset;
pfx->last_time = timestamp;
}