return buf;
}
+char* decescape(const char *s, const char *bad, size_t len) {
+ char *buf, *t;
+
+ /* Escapes all chars in bad, in addition to \ and " chars, in \nnn decimal style escaping. */
+
+ assert(s || len == 0);
+
+ t = buf = new(char, len * 4 + 1);
+ if (!buf)
+ return NULL;
+
+ for (size_t i = 0; i < len; i++) {
+ uint8_t u = (uint8_t) s[i];
+
+ if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"') || strchr(bad, u)) {
+ *(t++) = '\\';
+ *(t++) = '0' + (u / 100);
+ *(t++) = '0' + ((u / 10) % 10);
+ *(t++) = '0' + (u % 10);
+ } else
+ *(t++) = u;
+ }
+
+ *t = 0;
+ return buf;
+}
+
static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
assert(bad);
assert(t);
return xescape_full(s, bad, SIZE_MAX, 0);
}
char* octescape(const char *s, size_t len);
+char* decescape(const char *s, const char *bad, size_t len);
char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFlags flags);
char* shell_escape(const char *s, const char *bad);
test_octescape_one("\123\213\222", "\123\\213\\222");
}
+static void test_decescape_one(const char *s, const char *bad, const char *expected) {
+ _cleanup_free_ char *ret = NULL;
+
+ assert_se(ret = decescape(s, bad, strlen_ptr(s)));
+ log_debug("decescape(\"%s\") → \"%s\" (expected: \"%s\")", strnull(s), ret, expected);
+ assert_se(streq(ret, expected));
+}
+
+TEST(decescape) {
+ test_decescape_one(NULL, "bad", "");
+ test_decescape_one("foo", "", "foo");
+ test_decescape_one("foo", "f", "\\102oo");
+ test_decescape_one("foo", "o", "f\\111\\111");
+ test_decescape_one("go\"bb\\ledyg\x03ook\r\n", "", "go\\034bb\\092ledyg\\003ook\\013\\010");
+ test_decescape_one("\\xff\xff" "f", "f", "\\092x\\102\\102\\255\\102");
+ test_decescape_one("all", "all", "\\097\\108\\108");
+}
+
DEFINE_TEST_MAIN(LOG_DEBUG);