btrfs-progs: factor string escaping helpers from receive dump
The string escaping functionality is more generic and can be used in other commands (e.g. in dump-tree). Move it to the string utils. Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
1de113eb0c
commit
3d2e879463
|
@ -19,7 +19,6 @@
|
|||
#include "kerncompat.h"
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
@ -29,6 +28,7 @@
|
|||
#include "common/messages.h"
|
||||
#include "common/send-stream.h"
|
||||
#include "common/path-utils.h"
|
||||
#include "common/string-utils.h"
|
||||
#include "cmds/receive-dump.h"
|
||||
|
||||
#define PATH_CAT_OR_RET(function_name, outpath, path1, path2, ret) \
|
||||
|
@ -40,51 +40,6 @@
|
|||
} \
|
||||
})
|
||||
|
||||
/*
|
||||
* Print path and escape characters (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_len(const char *path, size_t path_len)
|
||||
{
|
||||
size_t i;
|
||||
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;
|
||||
}
|
||||
|
||||
static int print_path_escaped(const char *path)
|
||||
{
|
||||
return print_path_escaped_len(path, strlen(path));
|
||||
}
|
||||
|
||||
enum print_mode {
|
||||
PRINT_DUMP_NORMAL,
|
||||
PRINT_DUMP_SUBVOLUME,
|
||||
|
@ -115,7 +70,7 @@ static int __print_dump(enum print_mode mode, void *user, const char *path,
|
|||
|
||||
/* Unified header */
|
||||
printf("%-16s", title);
|
||||
ret = print_path_escaped(out_path);
|
||||
ret = string_print_escape_special(out_path);
|
||||
if (!fmt) {
|
||||
putchar('\n');
|
||||
return 0;
|
||||
|
@ -203,7 +158,7 @@ static int print_mksock(const char *path, void *user)
|
|||
static int print_symlink(const char *path, const char *lnk, void *user)
|
||||
{
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "symlink", "dest=");
|
||||
print_path_escaped(lnk);
|
||||
string_print_escape_special(lnk);
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
@ -216,7 +171,7 @@ static int print_rename(const char *from, const char *to, void *user)
|
|||
|
||||
PATH_CAT_OR_RET("rename", full_to, r->full_subvol_path, to, ret);
|
||||
PRINT_DUMP_NO_NEWLINE(user, from, "rename", "dest=");
|
||||
print_path_escaped(full_to);
|
||||
string_print_escape_special(full_to);
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
@ -224,7 +179,7 @@ static int print_rename(const char *from, const char *to, void *user)
|
|||
static int print_link(const char *path, const char *lnk, void *user)
|
||||
{
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "link", "dest=");
|
||||
print_path_escaped(lnk);
|
||||
string_print_escape_special(lnk);
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
@ -257,7 +212,7 @@ static int print_clone(const char *path, u64 offset, u64 len,
|
|||
|
||||
PATH_CAT_OR_RET("clone", full_path, r->full_subvol_path, clone_path, ret);
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "clone", "offset=%llu len=%llu from=", offset, len);
|
||||
print_path_escaped(full_path);
|
||||
string_print_escape_special(full_path);
|
||||
putchar(' ');
|
||||
printf("clone_offset=%llu\n", clone_offset);
|
||||
return 0;
|
||||
|
@ -271,9 +226,9 @@ static int print_set_xattr(const char *path, const char *name,
|
|||
const void *data, int len, void *user)
|
||||
{
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "set_xattr", "name=");
|
||||
print_path_escaped(name);
|
||||
string_print_escape_special(name);
|
||||
putchar(' ');
|
||||
print_path_escaped_len((char *)data, len);
|
||||
string_print_escape_special_len((const char *)data, len);
|
||||
putchar(' ');
|
||||
printf("len=%d\n", len);
|
||||
return 0;
|
||||
|
@ -283,7 +238,7 @@ static int print_remove_xattr(const char *path, const char *name, void *user)
|
|||
{
|
||||
|
||||
PRINT_DUMP_NO_NEWLINE(user, path, "remove_xattr", "name=");
|
||||
print_path_escaped(name);
|
||||
string_print_escape_special(name);
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include "common/string-utils.h"
|
||||
#include "common/messages.h"
|
||||
#include "common/parse-utils.h"
|
||||
|
@ -64,6 +65,46 @@ char *strncpy_null(char *dest, const char *src, size_t n)
|
|||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string and escape characters (in a C way) that could break the line.
|
||||
* Returns the length of the escaped characters. Unprintable characters are
|
||||
* escaped as octals. Usable for paths or text-like data like xattrs.
|
||||
*/
|
||||
int string_print_escape_special_len(const char *str, size_t str_len)
|
||||
{
|
||||
size_t i;
|
||||
int len = 0;
|
||||
|
||||
for (i = 0; i < str_len; i++) {
|
||||
char c = str[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;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function should be only used when parsing command arg, it won't return
|
||||
* error to its caller and rather exit directly just like usage().
|
||||
|
|
|
@ -24,6 +24,12 @@ int string_has_prefix(const char *str, const char *prefix);
|
|||
|
||||
char *strncpy_null(char *dest, const char *src, size_t n);
|
||||
|
||||
int string_print_escape_special_len(const char *str, size_t len);
|
||||
static inline int string_print_escape_special(const char *str)
|
||||
{
|
||||
return string_print_escape_special_len(str, strlen(str));
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers prefixed by arg_* can exit if the argument is invalid and are supposed
|
||||
* to be used when parsing command line options where the immediate exit is valid
|
||||
|
|
Loading…
Reference in New Issue