btrfs-progs: tests: update README, images, coding style
[platform/upstream/btrfs-progs.git] / send-dump.c
index 8540913..1591e0c 100644 (file)
@@ -28,6 +28,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <time.h>
+#include <ctype.h>
 #include <asm/types.h>
 #include <uuid/uuid.h>
 #include "utils.h"
 })
 
 /*
+ * Print path and escape chaacters (in a C way) that could break the line.
+ * Returns the length of the escaped characters. Unprintable characters are
+ * escaped as octals.
+ */
+static int print_path_escaped(const char *path)
+{
+       size_t i;
+       size_t path_len = strlen(path);
+       int len = 0;
+
+       for (i = 0; i < path_len; i++) {
+               char c = path[i];
+
+               len++;
+               switch (c) {
+               case '\a': putchar('\\'); putchar('a'); len++; break;
+               case '\b': putchar('\\'); putchar('b'); len++; break;
+               case '\e': putchar('\\'); putchar('e'); len++; break;
+               case '\f': putchar('\\'); putchar('f'); len++; break;
+               case '\n': putchar('\\'); putchar('n'); len++; break;
+               case '\r': putchar('\\'); putchar('r'); len++; break;
+               case '\t': putchar('\\'); putchar('t'); len++; break;
+               case '\v': putchar('\\'); putchar('v'); len++; break;
+               case ' ':  putchar('\\'); putchar(' '); len++; break;
+               case '\\': putchar('\\'); putchar('\\'); len++; break;
+               default:
+                         if (!isprint(c)) {
+                                 printf("\\%c%c%c",
+                                                 '0' + ((c & 0300) >> 6),
+                                                 '0' + ((c & 070) >> 3),
+                                                 '0' + (c & 07));
+                                 len += 3;
+                         } else {
+                                 putchar(c);
+                         }
+               }
+       }
+       return len;
+}
+
+/*
  * Underlying PRINT_DUMP, the only difference is how we handle
  * the full path.
  */
@@ -68,7 +110,16 @@ static int __print_dump(int subvol, void *user, const char *path,
        }
 
        /* Unified header */
-       printf("%-16s%-32s", title, out_path);
+       printf("%-16s", title);
+       ret = print_path_escaped(out_path);
+       if (!fmt) {
+               putchar('\n');
+               return 0;
+       }
+       /* Short paths are aligned to 32 chars; longer paths get a single space */
+       do {
+               putchar(' ');
+       } while (++ret < 32);
        va_start(args, fmt);
        /* Operation specified ones */
        vprintf(fmt, args);
@@ -223,16 +274,15 @@ static int print_chown(const char *path, u64 uid, u64 gid, void *user)
 
 static int sprintf_timespec(struct timespec *ts, char *dest, int max_size)
 {
-       struct tm *tm;
+       struct tm tm;
        int ret;
 
-       tm = localtime(&ts->tv_sec);
-       if (!tm) {
+       if (!localtime_r(&ts->tv_sec, &tm)) {
                error("failed to convert time %lld.%.9ld to local time",
                      (long long)ts->tv_sec, ts->tv_nsec);
                return -EINVAL;
        }
-       ret = strftime(dest, max_size, "%FT%T%z", tm);
+       ret = strftime(dest, max_size, "%FT%T%z", &tm);
        if (ret == 0) {
                error(
                "time %lld.%ld is too long to convert into readable string",