Skip to content

Commit bfed38f

Browse files
committed
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>
1 parent f3b7148 commit bfed38f

File tree

3 files changed

+56
-54
lines changed

3 files changed

+56
-54
lines changed

cmds/receive-dump.c

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "kerncompat.h"
2020
#include <limits.h>
2121
#include <time.h>
22-
#include <ctype.h>
2322
#include <errno.h>
2423
#include <stdarg.h>
2524
#include <stdio.h>
@@ -29,6 +28,7 @@
2928
#include "common/messages.h"
3029
#include "common/send-stream.h"
3130
#include "common/path-utils.h"
31+
#include "common/string-utils.h"
3232
#include "cmds/receive-dump.h"
3333

3434
#define PATH_CAT_OR_RET(function_name, outpath, path1, path2, ret) \
@@ -40,51 +40,6 @@
4040
} \
4141
})
4242

43-
/*
44-
* Print path and escape characters (in a C way) that could break the line.
45-
* Returns the length of the escaped characters. Unprintable characters are
46-
* escaped as octals.
47-
*/
48-
static int print_path_escaped_len(const char *path, size_t path_len)
49-
{
50-
size_t i;
51-
int len = 0;
52-
53-
for (i = 0; i < path_len; i++) {
54-
char c = path[i];
55-
56-
len++;
57-
switch (c) {
58-
case '\a': putchar('\\'); putchar('a'); len++; break;
59-
case '\b': putchar('\\'); putchar('b'); len++; break;
60-
case '\e': putchar('\\'); putchar('e'); len++; break;
61-
case '\f': putchar('\\'); putchar('f'); len++; break;
62-
case '\n': putchar('\\'); putchar('n'); len++; break;
63-
case '\r': putchar('\\'); putchar('r'); len++; break;
64-
case '\t': putchar('\\'); putchar('t'); len++; break;
65-
case '\v': putchar('\\'); putchar('v'); len++; break;
66-
case ' ': putchar('\\'); putchar(' '); len++; break;
67-
case '\\': putchar('\\'); putchar('\\'); len++; break;
68-
default:
69-
if (!isprint(c)) {
70-
printf("\\%c%c%c",
71-
'0' + ((c & 0300) >> 6),
72-
'0' + ((c & 070) >> 3),
73-
'0' + (c & 07));
74-
len += 3;
75-
} else {
76-
putchar(c);
77-
}
78-
}
79-
}
80-
return len;
81-
}
82-
83-
static int print_path_escaped(const char *path)
84-
{
85-
return print_path_escaped_len(path, strlen(path));
86-
}
87-
8843
enum print_mode {
8944
PRINT_DUMP_NORMAL,
9045
PRINT_DUMP_SUBVOLUME,
@@ -115,7 +70,7 @@ static int __print_dump(enum print_mode mode, void *user, const char *path,
11570

11671
/* Unified header */
11772
printf("%-16s", title);
118-
ret = print_path_escaped(out_path);
73+
ret = string_print_escape_special(out_path);
11974
if (!fmt) {
12075
putchar('\n');
12176
return 0;
@@ -203,7 +158,7 @@ static int print_mksock(const char *path, void *user)
203158
static int print_symlink(const char *path, const char *lnk, void *user)
204159
{
205160
PRINT_DUMP_NO_NEWLINE(user, path, "symlink", "dest=");
206-
print_path_escaped(lnk);
161+
string_print_escape_special(lnk);
207162
putchar('\n');
208163
return 0;
209164
}
@@ -216,15 +171,15 @@ static int print_rename(const char *from, const char *to, void *user)
216171

217172
PATH_CAT_OR_RET("rename", full_to, r->full_subvol_path, to, ret);
218173
PRINT_DUMP_NO_NEWLINE(user, from, "rename", "dest=");
219-
print_path_escaped(full_to);
174+
string_print_escape_special(full_to);
220175
putchar('\n');
221176
return 0;
222177
}
223178

224179
static int print_link(const char *path, const char *lnk, void *user)
225180
{
226181
PRINT_DUMP_NO_NEWLINE(user, path, "link", "dest=");
227-
print_path_escaped(lnk);
182+
string_print_escape_special(lnk);
228183
putchar('\n');
229184
return 0;
230185
}
@@ -257,7 +212,7 @@ static int print_clone(const char *path, u64 offset, u64 len,
257212

258213
PATH_CAT_OR_RET("clone", full_path, r->full_subvol_path, clone_path, ret);
259214
PRINT_DUMP_NO_NEWLINE(user, path, "clone", "offset=%llu len=%llu from=", offset, len);
260-
print_path_escaped(full_path);
215+
string_print_escape_special(full_path);
261216
putchar(' ');
262217
printf("clone_offset=%llu\n", clone_offset);
263218
return 0;
@@ -271,9 +226,9 @@ static int print_set_xattr(const char *path, const char *name,
271226
const void *data, int len, void *user)
272227
{
273228
PRINT_DUMP_NO_NEWLINE(user, path, "set_xattr", "name=");
274-
print_path_escaped(name);
229+
string_print_escape_special(name);
275230
putchar(' ');
276-
print_path_escaped_len((char *)data, len);
231+
string_print_escape_special_len((const char *)data, len);
277232
putchar(' ');
278233
printf("len=%d\n", len);
279234
return 0;
@@ -283,7 +238,7 @@ static int print_remove_xattr(const char *path, const char *name, void *user)
283238
{
284239

285240
PRINT_DUMP_NO_NEWLINE(user, path, "remove_xattr", "name=");
286-
print_path_escaped(name);
241+
string_print_escape_special(name);
287242
putchar('\n');
288243
return 0;
289244
}

common/string-utils.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <stdlib.h>
1919
#include <stdio.h>
2020
#include <limits.h>
21+
#include <ctype.h>
2122
#include "common/string-utils.h"
2223
#include "common/messages.h"
2324
#include "common/parse-utils.h"
@@ -64,6 +65,46 @@ char *strncpy_null(char *dest, const char *src, size_t n)
6465
return dest;
6566
}
6667

68+
/*
69+
* Print a string and escape characters (in a C way) that could break the line.
70+
* Returns the length of the escaped characters. Unprintable characters are
71+
* escaped as octals. Usable for paths or text-like data like xattrs.
72+
*/
73+
int string_print_escape_special_len(const char *str, size_t str_len)
74+
{
75+
size_t i;
76+
int len = 0;
77+
78+
for (i = 0; i < str_len; i++) {
79+
char c = str[i];
80+
81+
len++;
82+
switch (c) {
83+
case '\a': putchar('\\'); putchar('a'); len++; break;
84+
case '\b': putchar('\\'); putchar('b'); len++; break;
85+
case '\e': putchar('\\'); putchar('e'); len++; break;
86+
case '\f': putchar('\\'); putchar('f'); len++; break;
87+
case '\n': putchar('\\'); putchar('n'); len++; break;
88+
case '\r': putchar('\\'); putchar('r'); len++; break;
89+
case '\t': putchar('\\'); putchar('t'); len++; break;
90+
case '\v': putchar('\\'); putchar('v'); len++; break;
91+
case ' ': putchar('\\'); putchar(' '); len++; break;
92+
case '\\': putchar('\\'); putchar('\\'); len++; break;
93+
default:
94+
if (!isprint(c)) {
95+
printf("\\%c%c%c",
96+
'0' + ((c & 0300) >> 6),
97+
'0' + ((c & 070) >> 3),
98+
'0' + (c & 07));
99+
len += 3;
100+
} else {
101+
putchar(c);
102+
}
103+
}
104+
}
105+
return len;
106+
}
107+
67108
/*
68109
* This function should be only used when parsing command arg, it won't return
69110
* error to its caller and rather exit directly just like usage().

common/string-utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ int string_has_prefix(const char *str, const char *prefix);
2424

2525
char *strncpy_null(char *dest, const char *src, size_t n);
2626

27+
int string_print_escape_special_len(const char *str, size_t len);
28+
static inline int string_print_escape_special(const char *str)
29+
{
30+
return string_print_escape_special_len(str, strlen(str));
31+
}
32+
2733
/*
2834
* Helpers prefixed by arg_* can exit if the argument is invalid and are supposed
2935
* to be used when parsing command line options where the immediate exit is valid

0 commit comments

Comments
 (0)