- if (sis && !strcmp(na_child_get_string(sis, "state"), "enabled")) {
- uint64_t sis_saved_reported = na_child_get_uint64(sis, "size-saved", 0), sis_saved_percent = na_child_get_uint64(sis, "percentage-saved", 0);
- /* size-saved is actually a 32 bit number, so ... time for some guesswork. */
- if (sis_saved_reported >> 32) {
- /* In case they ever fix this bug. */
- sis_saved = sis_saved_reported;
+ if (sis == NULL)
+ continue;
+
+ sis_state = na_child_get_string(sis, "state");
+ if ((sis_state == NULL)
+ || (strcmp ("enabled", sis_state) != 0))
+ continue;
+
+ sis_saved_reported = na_child_get_uint64(sis, "size-saved", UINT64_MAX);
+ sis_saved_percent = na_child_get_uint64(sis, "percentage-saved", UINT64_MAX);
+
+ /* sis_saved_percent == 100 leads to division by zero below */
+ if ((sis_saved_reported == UINT64_MAX) || (sis_saved_percent > 99))
+ continue;
+
+ /* size-saved is actually a 32 bit number, so ... time for some guesswork. */
+ if ((sis_saved_reported >> 32) != 0) {
+ /* In case they ever fix this bug. */
+ sis_saved = sis_saved_reported;
+ } else {
+ /* The "size-saved" value is a 32bit unsigned integer. This is a bug and
+ * will hopefully be fixed in later versions. To work around the bug, try
+ * to figure out how often the 32bit integer wrapped around by using the
+ * "percentage-saved" value. Because the percentage is in the range
+ * [0-100], this should work as long as the saved space does not exceed
+ * 400 GBytes. */
+ uint64_t real_saved = sis_saved_percent * size_used / (100 - sis_saved_percent);
+ uint64_t overflow_guess = real_saved >> 32;
+ uint64_t guess1 = overflow_guess ? ((overflow_guess - 1) << 32) + sis_saved_reported : sis_saved_reported;
+ uint64_t guess2 = (overflow_guess << 32) + sis_saved_reported;
+ uint64_t guess3 = ((overflow_guess + 1) << 32) + sis_saved_reported;
+
+ if (real_saved < guess2) {
+ if ((real_saved - guess1) < (guess2 - real_saved))
+ sis_saved = guess1;
+ else
+ sis_saved = guess2;