]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - scrub/common.c
xfs_scrub: progress indicator
[thirdparty/xfsprogs-dev.git] / scrub / common.c
index 81869e48bf78e7a0ef19f7869b5332413318c2cf..18171d18b810b2ac512317ab6b0576cb88c6b9a1 100644 (file)
@@ -27,6 +27,7 @@
 #include "path.h"
 #include "xfs_scrub.h"
 #include "common.h"
+#include "progress.h"
 
 /*
  * Reporting Status to the Console
@@ -61,6 +62,14 @@ static const char *err_str[] = {
        [S_INFO]        = "Info",
 };
 
+/* If stream is a tty, clear to end of line to clean up progress bar. */
+static inline const char *stream_start(FILE *stream)
+{
+       if (stream == stderr)
+               return stderr_isatty ? CLEAR_EOL : "";
+       return stdout_isatty ? CLEAR_EOL : "";
+}
+
 /* Print a warning string and some warning text. */
 void
 __str_out(
@@ -84,7 +93,8 @@ __str_out(
                stream = stdout;
 
        pthread_mutex_lock(&ctx->lock);
-       fprintf(stream, "%s: %s: ", _(err_str[level]), descr);
+       fprintf(stream, "%s%s: %s: ", stream_start(stream), _(err_str[level]),
+                       descr);
        if (error) {
                fprintf(stream, _("%s."), strerror_r(error, buf, DESCR_BUFSZ));
        } else {
@@ -285,3 +295,85 @@ background_sleep(void)
        tv.tv_nsec = time % 1000000;
        nanosleep(&tv, NULL);
 }
+
+/*
+ * Return the input string with non-printing bytes escaped.
+ * Caller must free the buffer.
+ */
+char *
+string_escape(
+       const char              *in)
+{
+       char                    *str;
+       const char              *p;
+       char                    *q;
+       int                     x;
+
+       str = malloc(strlen(in) * 4);
+       if (!str)
+               return NULL;
+       for (p = in, q = str; *p != '\0'; p++) {
+               if (isprint(*p)) {
+                       *q = *p;
+                       q++;
+               } else {
+                       x = sprintf(q, "\\x%02x", *p);
+                       q += x;
+               }
+       }
+       *q = '\0';
+       return str;
+}
+
+/*
+ * Record another naming warning, and decide if it's worth
+ * complaining about.
+ */
+bool
+should_warn_about_name(
+       struct scrub_ctx        *ctx)
+{
+       bool                    whine;
+       bool                    res;
+
+       pthread_mutex_lock(&ctx->lock);
+       ctx->naming_warnings++;
+       whine = ctx->naming_warnings == TOO_MANY_NAME_WARNINGS;
+       res = ctx->naming_warnings < TOO_MANY_NAME_WARNINGS;
+       pthread_mutex_unlock(&ctx->lock);
+
+       if (whine && !(debug || verbose))
+               str_info(ctx, ctx->mntpoint,
+_("More than %u naming warnings, shutting up."),
+                               TOO_MANY_NAME_WARNINGS);
+
+       return debug || verbose || res;
+}
+
+/* Decide if a value is within +/- (n/d) of a desired value. */
+bool
+within_range(
+       struct scrub_ctx        *ctx,
+       unsigned long long      value,
+       unsigned long long      desired,
+       unsigned long long      abs_threshold,
+       unsigned int            n,
+       unsigned int            d,
+       const char              *descr)
+{
+       assert(n < d);
+
+       /* Don't complain if difference does not exceed an absolute value. */
+       if (value < desired && desired - value < abs_threshold)
+               return true;
+       if (value > desired && value - desired < abs_threshold)
+               return true;
+
+       /* Complain if the difference exceeds a certain percentage. */
+       if (value < desired * (d - n) / d)
+               return false;
+       if (value > desired * (d + n) / d)
+               return false;
+
+       return true;
+}