bus: add API calls to escape string components of objects paths

This commit is contained in:
Lennart Poettering 2013-11-21 01:03:26 +01:00
parent 850516e012
commit 28383ba189
12 changed files with 113 additions and 109 deletions

2
TODO
View file

@ -72,8 +72,6 @@ Features:
* sd-bus: support "const" properties as flag * sd-bus: support "const" properties as flag
* sd-bus: add api call to escape bus path components
* sd-event: when a handler returns an error, just turn off its event * sd-event: when a handler returns an error, just turn off its event
source, but do not return anything up to the event loop source, but do not return anything up to the event loop
caller. Instead add parameter to sd_event_request_quit() to take caller. Instead add parameter to sd_event_request_quit() to take

View file

@ -187,6 +187,10 @@ global:
sd_bus_error_is_set; sd_bus_error_is_set;
sd_bus_error_has_name; sd_bus_error_has_name;
/* Escaping */
sd_bus_label_escape;
sd_bus_label_unescape;
/* sd-memfd functions */ /* sd-memfd functions */
sd_memfd_new; sd_memfd_new;
sd_memfd_make; sd_memfd_make;

View file

@ -2712,3 +2712,75 @@ _public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) {
return -ENXIO; return -ENXIO;
} }
_public_ char *sd_bus_label_escape(const char *s) {
char *r, *t;
const char *f;
assert_return(s, NULL);
/* Escapes all chars that D-Bus' object path cannot deal
* with. Can be reversed with bus_path_unescape(). We special
* case the empty string. */
if (*s == 0)
return strdup("_");
r = new(char, strlen(s)*3 + 1);
if (!r)
return NULL;
for (f = s, t = r; *f; f++) {
/* Escape everything that is not a-zA-Z0-9. We also
* escape 0-9 if it's the first character */
if (!(*f >= 'A' && *f <= 'Z') &&
!(*f >= 'a' && *f <= 'z') &&
!(f > s && *f >= '0' && *f <= '9')) {
*(t++) = '_';
*(t++) = hexchar(*f >> 4);
*(t++) = hexchar(*f);
} else
*(t++) = *f;
}
*t = 0;
return r;
}
_public_ char *sd_bus_label_unescape(const char *f) {
char *r, *t;
assert_return(f, NULL);
/* Special case for the empty string */
if (streq(f, "_"))
return strdup("");
r = new(char, strlen(f) + 1);
if (!r)
return NULL;
for (t = r; *f; f++) {
if (*f == '_') {
int a, b;
if ((a = unhexchar(f[1])) < 0 ||
(b = unhexchar(f[2])) < 0) {
/* Invalid escape code, let's take it literal then */
*(t++) = '_';
} else {
*(t++) = (char) ((a << 4) | b);
f += 2;
}
} else
*(t++) = *f;
}
*t = 0;
return r;
}

View file

@ -39,6 +39,29 @@
#include "bus-util.h" #include "bus-util.h"
#include "bus-dump.h" #include "bus-dump.h"
static void test_bus_label_escape_one(const char *a, const char *b) {
_cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
assert_se(t = sd_bus_label_escape(a));
assert_se(streq(t, b));
assert_se(x = sd_bus_label_unescape(t));
assert_se(streq(a, x));
assert_se(y = sd_bus_label_unescape(b));
assert_se(streq(a, y));
}
static void test_bus_label_escape(void) {
test_bus_label_escape_one("foo123bar", "foo123bar");
test_bus_label_escape_one("foo.bar", "foo_2ebar");
test_bus_label_escape_one("foo_2ebar", "foo_5f2ebar");
test_bus_label_escape_one("", "_");
test_bus_label_escape_one("_", "_5f");
test_bus_label_escape_one("1", "_31");
test_bus_label_escape_one(":1", "_3a1");
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *copy = NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *copy = NULL;
int r, boolean; int r, boolean;
@ -294,5 +317,7 @@ int main(int argc, char *argv[]) {
assert_se(streq(c, "ccc")); assert_se(streq(c, "ccc"));
assert_se(streq(d, "3")); assert_se(streq(d, "3"));
test_bus_label_escape();
return 0; return 0;
} }

View file

@ -294,7 +294,7 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
if (!p) if (!p)
return 0; return 0;
e = bus_path_unescape(p); e = sd_bus_label_unescape(p);
if (!e) if (!e)
return -ENOMEM; return -ENOMEM;
@ -312,7 +312,7 @@ char *seat_bus_path(Seat *s) {
assert(s); assert(s);
t = bus_path_escape(s->id); t = sd_bus_label_escape(s->id);
if (!t) if (!t)
return NULL; return NULL;

View file

@ -499,7 +499,7 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
if (!p) if (!p)
return 0; return 0;
e = bus_path_unescape(p); e = sd_bus_label_unescape(p);
if (!e) if (!e)
return -ENOMEM; return -ENOMEM;
@ -517,7 +517,7 @@ char *session_bus_path(Session *s) {
assert(s); assert(s);
t = bus_path_escape(s->id); t = sd_bus_label_escape(s->id);
if (!t) if (!t)
return NULL; return NULL;

View file

@ -176,7 +176,7 @@ int machine_object_find(sd_bus *bus, const char *path, const char *interface, vo
if (!p) if (!p)
return 0; return 0;
e = bus_path_unescape(p); e = sd_bus_label_unescape(p);
if (!e) if (!e)
return -ENOMEM; return -ENOMEM;
@ -194,7 +194,7 @@ char *machine_bus_path(Machine *m) {
assert(m); assert(m);
e = bus_path_escape(m->name); e = sd_bus_label_escape(m->name);
if (!e) if (!e)
return NULL; return NULL;

View file

@ -23,6 +23,7 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "sd-bus.h"
#include "path-util.h" #include "path-util.h"
#include "util.h" #include "util.h"
#include "unit-name.h" #include "unit-name.h"
@ -459,7 +460,7 @@ char *unit_dbus_path_from_name(const char *name) {
assert(name); assert(name);
e = bus_path_escape(name); e = sd_bus_label_escape(name);
if (!e) if (!e)
return NULL; return NULL;
@ -474,7 +475,7 @@ int unit_name_from_dbus_path(const char *path, char **name) {
if (!e) if (!e)
return -EINVAL; return -EINVAL;
n = bus_path_unescape(e); n = sd_bus_label_unescape(e);
if (!n) if (!n)
return -ENOMEM; return -ENOMEM;

View file

@ -1356,78 +1356,6 @@ char *xescape(const char *s, const char *bad) {
return r; return r;
} }
char *bus_path_escape(const char *s) {
char *r, *t;
const char *f;
assert(s);
/* Escapes all chars that D-Bus' object path cannot deal
* with. Can be reversed with bus_path_unescape(). We special
* case the empty string. */
if (*s == 0)
return strdup("_");
r = new(char, strlen(s)*3 + 1);
if (!r)
return NULL;
for (f = s, t = r; *f; f++) {
/* Escape everything that is not a-zA-Z0-9. We also
* escape 0-9 if it's the first character */
if (!(*f >= 'A' && *f <= 'Z') &&
!(*f >= 'a' && *f <= 'z') &&
!(f > s && *f >= '0' && *f <= '9')) {
*(t++) = '_';
*(t++) = hexchar(*f >> 4);
*(t++) = hexchar(*f);
} else
*(t++) = *f;
}
*t = 0;
return r;
}
char *bus_path_unescape(const char *f) {
char *r, *t;
assert(f);
/* Special case for the empty string */
if (streq(f, "_"))
return strdup("");
r = new(char, strlen(f) + 1);
if (!r)
return NULL;
for (t = r; *f; f++) {
if (*f == '_') {
int a, b;
if ((a = unhexchar(f[1])) < 0 ||
(b = unhexchar(f[2])) < 0) {
/* Invalid escape code, let's take it literal then */
*(t++) = '_';
} else {
*(t++) = (char) ((a << 4) | b);
f += 2;
}
} else
*(t++) = *f;
}
*t = 0;
return r;
}
char *ascii_strlower(char *t) { char *ascii_strlower(char *t) {
char *p; char *p;

View file

@ -237,9 +237,6 @@ char *cunescape_length_with_prefix(const char *s, size_t length, const char *pre
char *xescape(const char *s, const char *bad); char *xescape(const char *s, const char *bad);
char *bus_path_escape(const char *s);
char *bus_path_unescape(const char *s);
char *ascii_strlower(char *path); char *ascii_strlower(char *path);
bool dirent_is_file(const struct dirent *de) _pure_; bool dirent_is_file(const struct dirent *de) _pure_;

View file

@ -282,6 +282,9 @@ int sd_bus_error_has_name(const sd_bus_error *e, const char *name);
&(x).bytes[8], &(x).bytes[9], &(x).bytes[10], &(x).bytes[11], \ &(x).bytes[8], &(x).bytes[9], &(x).bytes[10], &(x).bytes[11], \
&(x).bytes[12], &(x).bytes[13], &(x).bytes[14], &(x).bytes[15] &(x).bytes[12], &(x).bytes[13], &(x).bytes[14], &(x).bytes[15]
char *sd_bus_label_escape(const char *s);
char *sd_bus_label_unescape(const char *f);
_SD_END_DECLARATIONS; _SD_END_DECLARATIONS;
#endif #endif

View file

@ -351,29 +351,6 @@ static void test_memdup_multiply(void) {
free(dup); free(dup);
} }
static void test_bus_path_escape_one(const char *a, const char *b) {
_cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
assert_se(t = bus_path_escape(a));
assert_se(streq(t, b));
assert_se(x = bus_path_unescape(t));
assert_se(streq(a, x));
assert_se(y = bus_path_unescape(b));
assert_se(streq(a, y));
}
static void test_bus_path_escape(void) {
test_bus_path_escape_one("foo123bar", "foo123bar");
test_bus_path_escape_one("foo.bar", "foo_2ebar");
test_bus_path_escape_one("foo_2ebar", "foo_5f2ebar");
test_bus_path_escape_one("", "_");
test_bus_path_escape_one("_", "_5f");
test_bus_path_escape_one("1", "_31");
test_bus_path_escape_one(":1", "_3a1");
}
static void test_hostname_is_valid(void) { static void test_hostname_is_valid(void) {
assert(hostname_is_valid("foobar")); assert(hostname_is_valid("foobar"));
assert(hostname_is_valid("foobar.com")); assert(hostname_is_valid("foobar.com"));
@ -616,7 +593,6 @@ int main(int argc, char *argv[]) {
test_foreach_word_quoted(); test_foreach_word_quoted();
test_default_term_for_tty(); test_default_term_for_tty();
test_memdup_multiply(); test_memdup_multiply();
test_bus_path_escape();
test_hostname_is_valid(); test_hostname_is_valid();
test_u64log2(); test_u64log2();
test_get_process_comm(); test_get_process_comm();