src/client.c | 56 +++++++++++++++++----- src/client_cmd.c | 17 +++++- src/sanlock.h | 7 ++ tests/Makefile | 17 ++++-- tests/sanlk_path.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 202 insertions(+), 25 deletions(-)
New commits: commit fb4b2cbcc76f48d8da1af9d6f6da00e438b95d8e Author: David Teigland teigland@redhat.com Date: Fri Sep 21 10:32:15 2012 -0500
sanlock: print escape chars in path from status
Signed-off-by: David Teigland teigland@redhat.com
diff --git a/src/client_cmd.c b/src/client_cmd.c index ee96ae2..069f75f 100644 --- a/src/client_cmd.c +++ b/src/client_cmd.c @@ -73,14 +73,22 @@ static void status_client(struct sanlk_state *st, char *str, int debug) print_debug(str, st->str_len); }
+/* TODO: when path strings are exported, through status or inquire, we + should export into a malloced buffer the size of the standard chars + plus extra esc chars. */ + static void status_lockspace(struct sanlk_state *st, char *str, char *bin, int debug) { struct sanlk_lockspace *ls = (struct sanlk_lockspace *)bin; + char path[SANLK_PATH_LEN + 1]; + + memset(path, 0, sizeof(path)); + sanlock_path_export(path, ls->host_id_disk.path, sizeof(path));
printf("s %.48s:%llu:%s:%llu\n", ls->name, (unsigned long long)ls->host_id, - ls->host_id_disk.path, + path, (unsigned long long)ls->host_id_disk.offset);
if (st->str_len && debug) @@ -91,6 +99,7 @@ static void status_resource(struct sanlk_state *st, char *str, char *bin, int de { struct sanlk_resource *res = (struct sanlk_resource *)bin; struct sanlk_disk *disk; + char path[SANLK_PATH_LEN + 1]; int i;
printf("r %.48s:%.48s", res->lockspace_name, res->name); @@ -98,8 +107,10 @@ static void status_resource(struct sanlk_state *st, char *str, char *bin, int de for (i = 0; i < res->num_disks; i++) { disk = (struct sanlk_disk *)(bin + sizeof(struct sanlk_resource) + i * sizeof(struct sanlk_disk));
- printf(":%s:%llu", - disk->path, (unsigned long long)disk->offset); + memset(path, 0, sizeof(path)); + sanlock_path_export(path, disk->path, sizeof(path)); + + printf(":%s:%llu", path, (unsigned long long)disk->offset); }
if (res->flags & SANLK_RES_SHARED) diff --git a/src/sanlock.h b/src/sanlock.h index 457ab7a..8446ebe 100644 --- a/src/sanlock.h +++ b/src/sanlock.h @@ -18,7 +18,8 @@
#define SANLK_NAME_LEN 48
-/* max disk path length, includes terminating \0 byte */ +/* max disk path length, includes terminating \0 byte, and escape chars, + i.e. the strlen with esc chars inserted must still be less than 1024. */
#define SANLK_PATH_LEN 1024
commit 47bd55e66ae8b043136d10a99e8ebbff9d53bdc1 Author: Federico Simoncelli fsimonce@redhat.com Date: Fri Sep 21 10:13:42 2012 -0400
sanlock: expose sanlock path import and export utils
Signed-off-by: Federico Simoncelli fsimonce@redhat.com
diff --git a/src/client.c b/src/client.c index e8b61be..3c7287e 100644 --- a/src/client.c +++ b/src/client.c @@ -238,28 +238,56 @@ int sanlock_init(struct sanlk_lockspace *ls,
/* src has colons unescaped, dst should have them escaped with backslash */
-static void copy_path_out(char *dst, char *src) +size_t sanlock_path_export(char *dst, const char *src, size_t dstlen) { - int i, j = 0; + size_t j = 0, escaped = 0; + const char *p = src; + + while (j < dstlen) { + if (*p == ':' || *p == '\') { + if (!escaped) { + dst[j] = '\', escaped = 1; + goto next_loop; + } + + escaped = 0; + } + + dst[j] = *p;
- for (i = 0; i < strlen(src); i++) { - if (src[i] == ':') - dst[j++] = '\'; - dst[j++] = src[i]; + if (*p == '\0') return j; /* success */ + p++; + + next_loop: + j++; } + + return 0; }
/* src has colons escaped with backslash, dst should have backslash removed */
-static void copy_path_in(char *dst, char *src) +size_t sanlock_path_import(char *dst, const char *src, size_t dstlen) { - int i, j = 0; + size_t j = 0; + const char *p = src;
- for (i = 0; i < strlen(src); i++) { - if (src[i] == '\') - continue; - dst[j++] = src[i]; + while (j < dstlen) { + if (*p == '\') + goto next_loop; + + dst[j] = *p; + + if (*p == '\0') + return j; + + j++; + + next_loop: + p++; } + + return 0; }
int sanlock_register(void) @@ -636,7 +664,7 @@ int sanlock_res_to_str(struct sanlk_resource *res, char **str_ret)
for (d = 0; d < res->num_disks; d++) { memset(path, 0, sizeof(path)); - copy_path_out(path, res->disks[d].path); + sanlock_path_export(path, res->disks[d].path, sizeof(path));
ret = snprintf(str + pos, len - pos, ":%s:%llu", path, (unsigned long long)res->disks[d].offset); @@ -946,7 +974,7 @@ int sanlock_str_to_lockspace(char *str, struct sanlk_lockspace *ls) if (host_id) ls->host_id = atoll(host_id); if (path) - copy_path_in(ls->host_id_disk.path, path); + sanlock_path_import(ls->host_id_disk.path, path, sizeof(ls->host_id_disk.path)); if (offset) ls->host_id_disk.offset = atoll(offset);
diff --git a/src/sanlock.h b/src/sanlock.h index e36c40e..457ab7a 100644 --- a/src/sanlock.h +++ b/src/sanlock.h @@ -91,5 +91,7 @@ struct sanlk_lockspace { struct sanlk_disk host_id_disk; };
-#endif +size_t sanlock_path_export(char *dst, const char *src, size_t dstlen); +size_t sanlock_path_import(char *dst, const char *src, size_t dstlen);
+#endif diff --git a/tests/Makefile b/tests/Makefile index 838ad23..28f5d21 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,11 +2,13 @@ TARGET1 = devcount TARGET2 = sanlk_load TARGET3 = sanlk_client TARGET4 = killpath +TARGET5 = sanlk_path
SOURCE1 = devcount.c SOURCE2 = sanlk_load.c SOURCE3 = sanlk_client.c SOURCE4 = killpath.c +SOURCE5 = sanlk_path.c
CFLAGS += -D_GNU_SOURCE -g \ -Wall \ @@ -29,20 +31,23 @@ CFLAGS += -D_GNU_SOURCE -g \
LDFLAGS = -lrt -laio -lblkid -lsanlock
-all: $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) +all: $(TARGET1) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5)
$(TARGET1): $(SOURCE1) - $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCE1) -o $@ -L. -L../src + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src
$(TARGET2): $(SOURCE2) - $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCE2) -o $@ -L. -L../src + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src
$(TARGET3): $(SOURCE3) - $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCE3) -o $@ -L. -L../src + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src
$(TARGET4): $(SOURCE4) - $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCE4) -o $@ -L. -L../src + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src + +$(TARGET5): $(SOURCE5) + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ -L. -I../src -L../src
clean: - rm -f *.o *.so *.so.* $(TARGET) $(TARGET2) $(TARGET3) $(TARGET4) + rm -f *.o *.so *.so.* $(TARGET) $(TARGET2) $(TARGET3) $(TARGET4) $(TARGET5)
diff --git a/tests/sanlk_path.c b/tests/sanlk_path.c new file mode 100644 index 0000000..f9d8f6f --- /dev/null +++ b/tests/sanlk_path.c @@ -0,0 +1,130 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include "sanlock.h" +#include "sanlock_resource.h" + +#define DSTMAXSIZE 1024 + +static int __test_passed = 0; + +#define check_perror(expression, fmt, args...) \ +if (expression) { \ + __test_passed++; \ +} \ +else { \ + fprintf(stderr, "%s:%i " fmt "\n", __FILE__, __LINE__, ##args); \ + exit(1); \ +} + +void test_sanlock_path_export(void) +{ + int rv, dst_len; + char dst_str[DSTMAXSIZE]; + const char *src_str, *dst_exp; + + /* regular behavior, no escapes */ + src_str = "Hello World"; + dst_exp = src_str; + dst_len = strlen(dst_exp); + + memset(dst_str, 'X', DSTMAXSIZE); + + /* destination too short */ + rv = sanlock_path_export(dst_str, src_str, dst_len); + check_perror(rv == 0, "sanlock_path_export wrong return code: %u", rv); + check_perror(dst_str[dst_len] == 'X', + "sanlock_path_export buffer overflow"); + + /* destination long enough */ + rv = sanlock_path_export(dst_str, src_str, dst_len + 1); + check_perror(rv == dst_len, + "sanlock_path_export wrong return code: %u", rv); + check_perror(dst_str[dst_len] == '\0', + "sanlock_path_import destination not terminated"); + check_perror(!strncmp(dst_str, dst_exp, dst_len), + "sanlock_path_export destination is different"); + + /* special behavior, escapes */ + src_str = "Hello World:"; + dst_exp = "Hello World\:"; + dst_len = strlen(dst_exp); + + memset(dst_str, 'X', DSTMAXSIZE); + + /* destination too short */ + rv = sanlock_path_export(dst_str, src_str, dst_len); + check_perror(rv == 0, "sanlock_path_export wrong return code: %u", rv); + check_perror(dst_str[dst_len] == 'X', + "sanlock_path_export buffer overflow"); + + /* destination long enough */ + rv = sanlock_path_export(dst_str, src_str, dst_len + 1); + check_perror(rv == dst_len, + "sanlock_path_export wrong return code: %u", rv); + check_perror(dst_str[dst_len] == '\0', + "sanlock_path_import destination not terminated"); + check_perror(!strncmp(dst_str, dst_exp, dst_len), + "sanlock_path_export destination is different"); +} + +void test_sanlock_path_import(void) +{ + int rv, dst_len; + char dst_str[DSTMAXSIZE]; + const char *src_str, *dst_exp; + + /* regular behavior, no escapes */ + src_str = "Hello World"; + dst_exp = src_str; + dst_len = strlen(dst_exp); + + memset(dst_str, 'X', DSTMAXSIZE); + + /* destination too short */ + rv = sanlock_path_import(dst_str, src_str, dst_len); + check_perror(rv == 0, "sanlock_path_import wrong return code: %u", rv); + check_perror(dst_str[dst_len] == 'X', + "sanlock_path_import buffer overflow"); + + /* destination long enough */ + rv = sanlock_path_import(dst_str, src_str, dst_len + 1); + check_perror(rv == dst_len, + "sanlock_path_import wrong return code: %u", rv); + check_perror(dst_str[dst_len] == '\0', + "sanlock_path_import destination not terminated"); + check_perror(!strncmp(dst_str, dst_exp, dst_len), + "sanlock_path_import destination is different"); + + /* special behavior, escapes */ + src_str = "Hello World\:"; + dst_exp = "Hello World:"; + dst_len = strlen(dst_exp); + + memset(dst_str, 'X', DSTMAXSIZE); + + /* destination too short */ + rv = sanlock_path_import(dst_str, src_str, dst_len); + check_perror(rv == 0, "sanlock_path_import wrong return code: %u", rv); + check_perror(dst_str[dst_len] == 'X', + "sanlock_path_import buffer overflow"); + + /* destination long enough */ + rv = sanlock_path_import(dst_str, src_str, dst_len + 1); + check_perror(rv == dst_len, + "sanlock_path_import wrong return code: %u", rv); + check_perror(dst_str[dst_len] == '\0', + "sanlock_path_import destination not terminated"); + check_perror(!strncmp(dst_str, dst_exp, dst_len), + "sanlock_path_import destination is different"); +} + +int main(int argc, char *argv[]) +{ + test_sanlock_path_export(); + test_sanlock_path_import(); + printf("OK, %i tests sucessfully passed.\n", __test_passed); + return 0; +}
sanlock-devel@lists.fedorahosted.org