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(a)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(a)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(a)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(a)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;
+}