libqaeda

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

file.c (6331B)


      1 #include <stddef.h>
      2 #include <string.h>
      3 #include <stdio.h>
      4 #include <unistd.h>
      5 #include <fcntl.h>
      6 
      7 #include <llog.h>
      8 #include <hex.h>
      9 
     10 #include "lq/crypto.h"
     11 #include "lq/io.h"
     12 #include "lq/store.h"
     13 #include "lq/err.h"
     14 #include "lq/mem.h"
     15 #include "lq/query.h"
     16 #include "debug.h"
     17 
     18 static const int store_typ_file = 3;
     19 
     20 /// \todo key and val limits proper
     21 int lq_file_content_count(enum payload_e typ, LQStore *store, const char *key, size_t key_len) {
     22 	int r;
     23 	char **out;
     24 	char buf[LQ_STORE_KEY_MAX * 2 + 1];
     25 	char pfx[1024];
     26 
     27 	out = lq_alloc(sizeof(char**) * LQ_DIRS_MAX);
     28 	pfx[0] = (char)typ + 0x30;
     29 	b2h((const unsigned char*)key, (int)key_len, (unsigned char*)buf);
     30 	lq_cpy(pfx+1, buf, strlen(buf));
     31 
     32 	r = lq_files_pfx(store->userdata, out, LQ_DIRS_MAX, pfx, key_len + 1);
     33 
     34 	lq_free(out);
     35 
     36 	return r;
     37 }
     38 
     39 int lq_file_content_get(enum payload_e typ, LQStore *store, const char *key, size_t key_len, char *value, size_t *value_len) {
     40 	int f;
     41 	size_t l;
     42 	size_t c;
     43 	char buf[LQ_STORE_KEY_MAX * 2 + 1];
     44 	char path[1024];
     45 	char *p;
     46 
     47 	if (store->store_typ != store_typ_file) {
     48 		return ERR_COMPAT;
     49 	}
     50 
     51 	// \todo dry
     52 	p = (char*)store->userdata;
     53 	lq_cpy(path, p, strlen(p) + 1);
     54 	p = path + strlen(path);
     55 	b2h((const unsigned char*)key, (int)key_len, (unsigned char*)buf);
     56 	sprintf(p, "%d%s", (char)typ, buf);
     57 	f = lq_open(path, O_RDONLY, S_IRUSR);
     58 	if (f < 0) {
     59 		return ERR_NOENT;
     60 	}
     61 
     62 	p = value;
     63 	l = 0;
     64 	while (1) {
     65 		c = lq_read(f, p, *value_len - l);
     66 		if (c == 0) {
     67 			break;
     68 		}
     69 		l += c;
     70 		if (l > *value_len) {
     71 			lq_close(f);
     72 			return ERR_OVERFLOW;
     73 		}
     74 		p += c;	
     75 	}
     76 	lq_close(f);
     77 
     78 	*value_len = l;
     79 
     80 	debug_x(LLOG_DEBUG, "store.file", "get file", 2, MORGEL_TYP_STR, 0, "path", path, MORGEL_TYP_NUM, 0, "bytes", *value_len);
     81 
     82 	return ERR_OK;
     83 
     84 }
     85 
     86 int lq_file_content_put(enum payload_e typ, LQStore *store, const char *key, size_t *key_len, char *value, size_t value_len) {
     87 	size_t c;
     88 	size_t l;
     89 	char buf[LQ_STORE_KEY_MAX - 1];
     90 	char path[1024];
     91 	char *p;
     92 	int f;
     93 
     94 	if (*key_len > (LQ_STORE_KEY_MAX / 2) - 1) {
     95 		return ERR_OVERFLOW;
     96 	}
     97 	if (store->store_typ != store_typ_file) {
     98 		return ERR_COMPAT;
     99 	}
    100 	p = (char*)store->userdata;
    101 	lq_cpy(path, p, strlen(p) + 1);
    102 	p = path + strlen(path);
    103 	b2h((const unsigned char*)key, (int)*key_len, (unsigned char*)buf);
    104 	sprintf(p, "%d%s", (char)typ, (unsigned char*)buf);
    105 	f = lq_open(path, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
    106 	if (f < 0) {
    107 		return ERR_NOENT;
    108 	}
    109 	l = value_len;
    110 	p = value;
    111 	while (l > 0) {
    112 		c = write(f, p, l);
    113 		if (c < 0) {
    114 			lq_close(f);
    115 			return ERR_WRITE;
    116 		}
    117 		if (c == 0) {
    118 			break;
    119 		}
    120 		l -= c;
    121 		p += c;
    122 	}
    123 	debug_x(LLOG_DEBUG, "store.file", "put file", 2, MORGEL_TYP_STR, 0, "path", path, MORGEL_TYP_NUM, 0, "bytes", c);
    124 	lq_close(f);
    125 	return ERR_OK;
    126 }
    127 
    128 void lq_file_content_free(LQStore *store) {
    129 	lq_free(store->userdata);
    130 	lq_free(store);
    131 }
    132 
    133 /**
    134  * \todo DRY with lq_files_pfx
    135  * \todo prefix mismatches leak?
    136  */
    137 static int query_list(const char *path, char **files, size_t files_len, const char *prefix, char prefix_len) {
    138 	int r;
    139 	int i;
    140 	int c;
    141 	size_t l;
    142 
    143 	c = 0;
    144 	r = lq_files(path, files, files_len);
    145 	for (i = 0; i < r; i++) {
    146 		l = strlen(*(files+i));
    147 		if (l < prefix_len) {
    148 			lq_free(*(files+i));
    149 		}
    150 		if (!lq_cmp(prefix, *(files+i), prefix_len)) {
    151 	//		lq_free(*(files+c));// attempt at stopping mismatch leak.
    152 			*(files+c) = *(files+i);
    153 			c++;
    154 		}
    155 	}
    156 	return c;
    157 }
    158 
    159 /// \todo  DRY with lq_file_count
    160 LQQuery* lq_query_new(enum payload_e typ, LQStore *store, const char *key, size_t key_len) {
    161 	LQQuery *query;
    162 	//char **out;
    163 	char buf[LQ_STORE_KEY_MAX * 2 + 1];
    164 	char pfx[1024];
    165 
    166 	query = lq_alloc(sizeof(LQQuery));
    167 	lq_zero(query, sizeof(LQQuery));
    168 	query->files = lq_alloc(sizeof(char**) * LQ_DIRS_MAX);
    169 	pfx[0] = (char)typ + 0x30;
    170 	b2h((const unsigned char*)key, (int)key_len, (unsigned char*)buf);
    171 	lq_cpy(pfx+1, buf, strlen(buf) + 1);
    172 
    173 	key_len *= 2;
    174 	query->typ = typ;
    175 	query->files_len = query_list(store->userdata, query->files, LQ_DIRS_MAX, pfx, key_len + 1);
    176 	if (query->files_len == 0) {
    177 		return NULL;
    178 	}
    179 	query->value = lq_alloc(LQ_STORE_VAL_MAX);
    180 	query->key = lq_alloc(LQ_STORE_KEY_MAX);
    181 	query->store = store;
    182 	query->state = LQ_QUERY_READY;
    183 
    184 	debug_x(LLOG_DEBUG, "store.file", "query", 2, MORGEL_TYP_STR, 0, "pfx", key, MORGEL_TYP_NUM, 0, "typ", (int)typ);
    185 
    186 	return query;
    187 }
    188 
    189 int lq_query_next(LQQuery *query) {
    190 	int r;
    191 	char *p;
    192 	//char b[LQ_STORE_KEY_MAX];
    193 
    194 	if (query->state & LQ_QUERY_EOF) {
    195 		return ERR_EOF;	
    196 	}
    197 	p = *(query->files + query->files_cur) + 1;
    198 	query->key_len = h2b(p, (char*)query->key);
    199 	if (query->key_len == 0) {
    200 		query->state = LQ_QUERY_GONER;
    201 		return ERR_ENCODING;
    202 	}
    203 	query->value_len = LQ_STORE_VAL_MAX;
    204 	r = query->store->get(query->typ, query->store, query->key, query->key_len, query->value, &query->value_len);
    205 	if (r != ERR_OK) {
    206 		query->value_len = 0;
    207 		query->state = LQ_QUERY_GONER;
    208 		return ERR_FAIL;
    209 	}
    210 	if (++query->files_cur == query->files_len) {
    211 		query->state |= LQ_QUERY_EOF;
    212 	}
    213 	return ERR_OK;
    214 }
    215 
    216 int lq_query_get_val_len(LQQuery *query) {
    217 	if (!(query->state & LQ_QUERY_READY)) {
    218 		return -1;
    219 	}
    220 	return query->value_len;
    221 }
    222 
    223 char* lq_query_get_val(LQQuery *query) {
    224 	if (!(query->state & LQ_QUERY_READY)) {
    225 		return NULL;
    226 	}
    227 	return query->value;
    228 }
    229 
    230 int lq_query_get_key_len(LQQuery *query) {
    231 	if (!(query->state & LQ_QUERY_READY)) {
    232 		return -1;
    233 	}
    234 	return query->key_len;
    235 }
    236 
    237 char* lq_query_get_key(LQQuery *query) {
    238 	if (!(query->state & LQ_QUERY_READY)) {
    239 		return NULL;
    240 	}
    241 	return query->key;
    242 }
    243 
    244 void lq_query_free(LQQuery *query) {
    245 	char *p;
    246 	int i;
    247 
    248 	i = 0;
    249 	while(1) {
    250 		if (*((query->files)+i) != NULL) {
    251 			break;
    252 		}
    253 		lq_free(*((query->files)+i));
    254 		*((query->files)+i) = NULL;
    255 		i++;
    256 	}
    257 	lq_free(query->files);
    258 	lq_free(query->key);
    259 	lq_free(query->value);
    260 	lq_free(query);
    261 }
    262 
    263 struct lq_store_t LQFileContent = {
    264 	.store_typ = store_typ_file,
    265 	.userdata = "",
    266 	.get = lq_file_content_get,	
    267 	.put = lq_file_content_put,
    268 	.count = lq_file_content_count,
    269 	.free = lq_file_content_free,
    270 };
    271 
    272 LQStore* lq_store_new(const char *spec) {
    273 	int l;
    274 	LQStore *store;
    275 
    276 	l = strlen(spec) + 1;
    277 	store = lq_alloc(sizeof(LQStore));
    278 	lq_cpy(store, &LQFileContent, sizeof(LQFileContent));
    279 	store->userdata = lq_alloc(l);
    280 	lq_cpy(store->userdata, spec, l);
    281 	return store;
    282 }
    283 
    284 void lq_store_free(LQStore *store) {
    285 	lq_free(store->userdata);
    286 	lq_free(store);
    287 }