commit 31981858daa0987be527d21cb5c7264b586e9267
parent 52e141c3b456e6a6179f56b3e1ab6597cdc44e56
Author: lash <dev@holbrook.no>
Date: Sun, 4 May 2025 12:00:34 +0100
Add store query module
Diffstat:
11 files changed, 263 insertions(+), 43 deletions(-)
diff --git a/src/aux/liblash/src/llog/Makefile b/src/aux/liblash/src/llog/Makefile
@@ -6,11 +6,14 @@ VERSION = 0.0.1
all: $(OBJS)
-test: all
- $(CC) $(CFLAGS) test.c llog.o hex.o -o test.out $(LDFLAGS)
+hex:
+ make -C ../hex all
+
+test: hex all
+ $(CC) $(CFLAGS) test.c llog.o ../hex/hex.o -o test.out $(LDFLAGS)
%.o: %.c
- $(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
+ $(CC) $(CFLAGS) -I../hex -c $< -o $@ $(LDFLAGS)
clean:
rm -vf *.o
@@ -21,8 +24,6 @@ archive:
git archive --format=tar.gz HEAD -o llog-$(VERSION).tar.gz
%.so.o: %.c
- $(CC) $(CFLAGS) -c $< -o $@ -fpic
+ $(CC) $(CFLAGS) -I../hex -c $< -o $@ -fpic
shared: $(SOBJS)
-
-
diff --git a/src/aux/liblash/src/llog/hex.c b/src/aux/liblash/src/llog/hex.c
@@ -1,21 +0,0 @@
-#include <stdio.h>
-
-char *_x = "0123456789abcdef";
-
-void b2h(const unsigned char *data, int l, unsigned char *zHex) {
- unsigned int i;
-
- for (i = 0; i < l; i++) {
- sprintf((char*)zHex+(i*2), "%02x", *(data+i));
- }
-}
-
-char* c2h(char in, char *out) {
- char i;
- i = in & 0x0f;
- *(out+1) = *(_x+i);
- in >>= 4;
- i = in & 0x0f;
- *out = *(_x+i);
- return out;
-}
diff --git a/src/aux/liblash/src/llog/llog.c b/src/aux/liblash/src/llog/llog.c
@@ -1,7 +1,5 @@
#include "llog.h"
-
-extern void b2h(const unsigned char *b, int l, char *hx);
-extern char* c2h(char in, char *out);
+#include "hex.h"
char lloglvl_str[][4] = {
diff --git a/src/aux/liblash/src/rerr/rerr.c b/src/aux/liblash/src/rerr/rerr.c
@@ -23,6 +23,7 @@ char *rerr_base[3] = {
"Wrong byteorder",
"Value too large",
"Value too small",
+ "End of file",
#endif
};
#endif
diff --git a/src/aux/liblash/src/rerr/rerr.h b/src/aux/liblash/src/rerr/rerr.h
@@ -16,6 +16,7 @@ enum err_base_e {
ERR_BYTEORDER,
ERR_OVERFLOW,
ERR_UNDERFLOW,
+ ERR_EOF,
};
#ifndef RERR_N_PFX
diff --git a/src/io/std.c b/src/io/std.c
@@ -51,6 +51,7 @@ static int fltr_files(const struct dirent *d) {
/**
* \todo scandir calls malloc, so lq_alloc needs malloc alias that maps to it.
+ * \todo strdup doubles the mem needed for the iteration, instead need to keep scandir state and release after treatment
*/
int lq_files(const char *path, char **files, size_t files_len) {
int r;
@@ -66,7 +67,8 @@ int lq_files(const char *path, char **files, size_t files_len) {
return -2;
}
for (i = 0; i < r; i++) {
- *(files+i) = (*(ls+i))->d_name;
+ //*(files+i) = (*(ls+i))->d_name;
+ *(files+i) = strdup((*(ls+i))->d_name);
}
*(files+i+1) = NULL;
lq_free(ls);
diff --git a/src/lq/query.h b/src/lq/query.h
@@ -0,0 +1,27 @@
+#ifndef LIBQAEDA_QUERY_H_
+#define LIBQAEDA_QUERY_H_
+
+enum lq_query_state_e {
+ LQ_QUERY_EMPTY = 0,
+ LQ_QUERY_READY = 1,
+ LQ_QUERY_GONER = 2,
+ LQ_QUERY_EOF = 4,
+};
+
+typedef struct lq_query_t LQQuery;
+struct lq_query_t {
+ LQStore *store;
+ enum payload_e typ;
+ int state;
+ char **files;
+ size_t files_len;
+ size_t files_cur;
+ char *value;
+ size_t value_len;
+};
+
+LQQuery* lq_query_new(enum payload_e typ, LQStore *store, const char *key, size_t key_len);
+int lq_query_next(LQQuery *query);
+void lq_query_free(LQQuery *query);
+
+#endif // LIBQAEDA_QUERY_H_
diff --git a/src/store/file.c b/src/store/file.c
@@ -12,6 +12,7 @@
#include "lq/store.h"
#include "lq/err.h"
#include "lq/mem.h"
+#include "lq/query.h"
#include "debug.h"
static const int store_typ_file = 3;
@@ -20,7 +21,7 @@ static const int store_typ_file = 3;
int lq_file_content_count(enum payload_e typ, LQStore *store, const char *key, size_t key_len) {
int r;
char **out;
- char buf[LQ_DIGEST_LEN * 2 + 1];
+ char buf[LQ_STORE_KEY_MAX * 2 + 1];
char pfx[1024];
out = lq_alloc(sizeof(char**) * LQ_DIRS_MAX);
@@ -39,7 +40,7 @@ int lq_file_content_get(enum payload_e typ, LQStore *store, const char *key, siz
int f;
size_t l;
size_t c;
- char buf[LQ_DIGEST_LEN * 2 + 1];
+ char buf[LQ_STORE_KEY_MAX * 2 + 1];
char path[1024];
char *p;
@@ -129,6 +130,102 @@ void lq_file_content_free(LQStore *store) {
lq_free(store);
}
+/**
+ * \todo DRY with lq_files_pfx
+ * \todo prefix mismatches leak?
+ */
+static int query_list(const char *path, char **files, size_t files_len, const char *prefix, char prefix_len) {
+ int r;
+ int i;
+ int c;
+ size_t l;
+
+ c = 0;
+ r = lq_files(path, files, files_len);
+ for (i = 0; i < r; i++) {
+ l = strlen(*(files+i));
+ if (l < prefix_len) {
+ lq_free(*(files+i));
+ }
+ if (!lq_cmp(prefix, *(files+i), prefix_len)) {
+ // lq_free(*(files+c));// attempt at stopping mismatch leak.
+ *(files+c) = *(files+i);
+ c++;
+ }
+ }
+ return c;
+}
+
+/// \todo DRY with lq_file_count
+LQQuery* lq_query_new(enum payload_e typ, LQStore *store, const char *key, size_t key_len) {
+ LQQuery *query;
+ //char **out;
+ char buf[LQ_STORE_KEY_MAX * 2 + 1];
+ char pfx[1024];
+
+ query = lq_alloc(sizeof(LQQuery));
+ lq_zero(query, sizeof(LQQuery));
+ query->files = lq_alloc(sizeof(char**) * LQ_DIRS_MAX);
+ pfx[0] = (char)typ + 0x30;
+ b2h((const unsigned char*)key, (int)key_len, (unsigned char*)buf);
+ lq_cpy(pfx+1, buf, strlen(buf) + 1);
+
+ key_len *= 2;
+ query->typ = typ;
+ query->files_len = query_list(store->userdata, query->files, LQ_DIRS_MAX, pfx, key_len + 1);
+ if (query->files_len == 0) {
+ return NULL;
+ }
+ query->value = lq_alloc(LQ_STORE_VAL_MAX);
+ query->store = store;
+ query->state = LQ_QUERY_READY;
+
+ return query;
+}
+
+int lq_query_next(LQQuery *query) {
+ int r;
+ char *p;
+ char b[LQ_STORE_KEY_MAX];
+
+ if (query->state & LQ_QUERY_EOF) {
+ return ERR_EOF;
+ }
+ p = *(query->files + query->files_cur) + 1;
+ r = h2b(p, (char*)b);
+ if (r == 0) {
+ query->state = LQ_QUERY_GONER;
+ return ERR_ENCODING;
+ }
+ r = query->store->get(query->typ, query->store, b, r, query->value, &query->value_len);
+ if (r != ERR_OK) {
+ query->state = LQ_QUERY_GONER;
+ return ERR_FAIL;
+ }
+ if (query->files_cur++ == query->files_len) {
+ query->state = LQ_QUERY_EOF;
+ }
+ return ERR_OK;
+}
+
+void lq_query_free(LQQuery *query) {
+ char *p;
+ int i;
+
+ i = 0;
+ while(1) {
+ if (*((query->files)+i) != NULL) {
+ break;
+ }
+ lq_free(*((query->files)+i));
+ *((query->files)+i) = NULL;
+ i++;
+ }
+ lq_free(query->files);
+ lq_free(query->value);
+ lq_free(query);
+}
+
struct lq_store_t LQFileContent = {
.store_typ = store_typ_file,
.userdata = "",
diff --git a/src/test/Makefile b/src/test/Makefile
@@ -7,8 +7,8 @@ LIBS := ../asn1/defs_asn1_tab.o `pkg-config --libs libtasn1 libgcrypt` -L.. -L..
LDFLAGS := -lcheck $(LIBS)
COMMONOBJS = ../mem/std.o ../lq/config.o ../lq/err.o ../lq/base.o ../debug.o
-all: build all-tests
-#all: build one-test
+#all: build all-tests
+all: build one-test
all-tests:
cK_FORK=no LD_LIBRARY_PATH=`realpath ../aux/lib` ./test_test_bin
@@ -20,9 +20,10 @@ all-tests:
CK_FORK=no LD_LIBRARY_PATH=`realpath ../aux/lib` ./test_envelope_bin
CK_FORK=no LD_LIBRARY_PATH=`realpath ../aux/lib` ./test_trust_bin
CK_FORK=no LD_LIBRARY_PATH=`realpath ../aux/lib` ./test_store_bin
+ CK_FORK=no LD_LIBRARY_PATH=`realpath ../aux/lib` ./test_query_bin
one-test: build
- CK_FORK=no LD_LIBRARY_PATH=`realpath ../aux/lib` ./test_envelope_bin
+ CK_FORK=no LD_LIBRARY_PATH=`realpath ../aux/lib` ./test_query_bin
test: all
@@ -39,6 +40,7 @@ build:
$(CC) $(CFLAGS) test_envelope.c -o test_envelope_bin $(COMMONOBJS) ../store/dummy.o $(LDFLAGS) -lgcrypt
$(CC) $(CFLAGS) test_trust.c -o test_trust_bin $(COMMONOBJS) $(LDFLAGS)
$(CC) $(CFLAGS) test_store.c -o test_store_bin $(COMMONOBJS) $(LDFLAGS) -lgcrypt
+ $(CC) $(CFLAGS) test_query.c -o test_query_bin $(COMMONOBJS) $(LDFLAGS) -lgcrypt
clean:
rm -vf test_*_bin
diff --git a/src/test/test_query.c b/src/test/test_query.c
@@ -0,0 +1,112 @@
+#include <check.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lq/store.h"
+#include "lq/mem.h"
+#include "lq/query.h"
+#include "lq/io.h"
+#include "lq/err.h"
+
+extern LQStore LQFileContent;
+
+/**
+ * \todo DRY file store dir creation
+ */
+START_TEST(check_query_full) {
+ int r;
+ LQStore store;
+ char path[LQ_PATH_MAX];
+ char *k;
+ char *v;
+ size_t kl;
+ size_t vl;
+ LQQuery *query;
+
+ lq_cpy(&store, &LQFileContent, sizeof(LQStore));
+ lq_cpy(path, "/tmp/lqstore_file_XXXXXX", 25);
+ store.userdata = mktempdir(path);
+ *((char*)(store.userdata+24)) = '/';
+ *((char*)(store.userdata+25)) = 0x0;
+
+ k = "aaa";
+ v = "foo";
+ kl = 3;
+ vl = 3;
+ store.put(LQ_CONTENT_RAW, &store, k, &kl, v, vl);
+
+ k = "ab";
+ v = "bar";
+ kl = 2;
+ vl = 3;
+ store.put(LQ_CONTENT_RAW, &store, k, &kl, v, vl);
+
+ k = "aaa";
+ v = "inky";
+ kl = 3;
+ vl = 4;
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
+
+ k = "aab";
+ v = "pinky";
+ kl = 3;
+ vl = 5;
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
+
+ k = "b";
+ v = "blinky";
+ kl = 1;
+ vl = 6;
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
+
+ k = "bbc";
+ v = "clyde";
+ kl = 3;
+ vl = 5;
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
+
+ k = "bbc";
+ v = "clyde";
+ kl = 3;
+ vl = 5;
+ store.put(LQ_CONTENT_CERT, &store, k, &kl, v, vl);
+
+ query = lq_query_new(LQ_CONTENT_RAW, &store, "aa", 2);
+ ck_assert_ptr_nonnull(query);
+
+ r = lq_query_next(query);
+ ck_assert_int_eq(r, ERR_OK);
+ r = lq_query_next(query);
+ ck_assert_int_eq(r, ERR_OK);
+ r = lq_query_next(query);
+ ck_assert_int_eq(r, ERR_EOF);
+}
+END_TEST
+
+Suite * common_suite(void) {
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("query");
+ tc = tcase_create("files");
+ tcase_add_test(tc, check_query_full);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
+
+int main(void) {
+ int n_fail;
+
+ Suite *s;
+ SRunner *sr;
+
+ s = common_suite();
+ sr = srunner_create(s);
+
+ srunner_run_all(sr, CK_VERBOSE);
+ n_fail = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ return (n_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/test/test_store.c b/src/test/test_store.c
@@ -28,43 +28,43 @@ START_TEST(check_store_count) {
v = "foo";
kl = 3;
vl = 3;
- store.put(LQ_CONTENT_RAW, &store, k, &kl, v, vl),
+ store.put(LQ_CONTENT_RAW, &store, k, &kl, v, vl);
k = "ab";
v = "bar";
kl = 2;
vl = 3;
- store.put(LQ_CONTENT_RAW, &store, k, &kl, v, vl),
+ store.put(LQ_CONTENT_RAW, &store, k, &kl, v, vl);
k = "aaa";
v = "inky";
kl = 3;
vl = 4;
- store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl),
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
k = "aab";
v = "pinky";
kl = 3;
vl = 5;
- store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl),
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
k = "b";
v = "blinky";
kl = 1;
vl = 6;
- store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl),
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
k = "bbc";
v = "clyde";
kl = 3;
vl = 5;
- store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl),
+ store.put(LQ_CONTENT_MSG, &store, k, &kl, v, vl);
k = "bbc";
v = "clyde";
kl = 3;
vl = 5;
- store.put(LQ_CONTENT_CERT, &store, k, &kl, v, vl),
+ store.put(LQ_CONTENT_CERT, &store, k, &kl, v, vl);
r = store.count(LQ_CONTENT_MSG, &store, "aa", 2);