util: Add shell_escape
This is for shell-style \ escaping rather than quoting, which while it has the same effect in produced shell commands, is not exclusively useful for shell commands. shell_escape would be useful for producing sed commands, as you would be able to \ escape the normal special characters, plus whichever argument separator was chosen; or it could be used to escape arguments passed to the overlayfs mount command.
This commit is contained in:
parent
8ef24e7a4f
commit
61ee693981
|
@ -6537,6 +6537,32 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
|
||||
assert(bad);
|
||||
|
||||
for (; *s; s++) {
|
||||
if (*s == '\\' || strchr(bad, *s))
|
||||
*(t++) = '\\';
|
||||
|
||||
*(t++) = *s;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *shell_escape(const char *s, const char *bad) {
|
||||
char *r, *t;
|
||||
|
||||
r = new(char, strlen(s)*2+1);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
t = strcpy_backslash_escaped(r, s, bad);
|
||||
*t = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *shell_maybe_quote(const char *s) {
|
||||
const char *p;
|
||||
char *r, *t;
|
||||
|
@ -6563,13 +6589,7 @@ char *shell_maybe_quote(const char *s) {
|
|||
*(t++) = '"';
|
||||
t = mempcpy(t, s, p - s);
|
||||
|
||||
for (; *p; p++) {
|
||||
|
||||
if (strchr(SHELL_NEED_ESCAPE, *p))
|
||||
*(t++) = '\\';
|
||||
|
||||
*(t++) = *p;
|
||||
}
|
||||
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
|
||||
|
||||
*(t++)= '"';
|
||||
*t = 0;
|
||||
|
|
|
@ -919,6 +919,7 @@ void cmsg_close_all(struct msghdr *mh);
|
|||
|
||||
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
|
||||
|
||||
char *shell_escape(const char *s, const char *bad);
|
||||
char *shell_maybe_quote(const char *s);
|
||||
|
||||
int parse_mode(const char *s, mode_t *ret);
|
||||
|
|
|
@ -2100,6 +2100,21 @@ static void test_sparse_write(void) {
|
|||
test_sparse_write_one(fd, test_e, sizeof(test_e));
|
||||
}
|
||||
|
||||
static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
|
||||
_cleanup_free_ char *r;
|
||||
|
||||
assert_se(r = shell_escape(s, bad));
|
||||
assert_se(streq_ptr(r, expected));
|
||||
}
|
||||
|
||||
static void test_shell_escape(void) {
|
||||
test_shell_escape_one("", "", "");
|
||||
test_shell_escape_one("\\", "", "\\\\");
|
||||
test_shell_escape_one("foobar", "", "foobar");
|
||||
test_shell_escape_one("foobar", "o", "f\\o\\obar");
|
||||
test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
|
||||
}
|
||||
|
||||
static void test_shell_maybe_quote_one(const char *s, const char *expected) {
|
||||
_cleanup_free_ char *r;
|
||||
|
||||
|
@ -2264,6 +2279,7 @@ int main(int argc, char *argv[]) {
|
|||
test_same_fd();
|
||||
test_uid_ptr();
|
||||
test_sparse_write();
|
||||
test_shell_escape();
|
||||
test_shell_maybe_quote();
|
||||
test_parse_mode();
|
||||
test_tempfn();
|
||||
|
|
Loading…
Reference in a new issue