Rizin
unix-like reverse engineering framework and cli tools
sdb.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2018 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: MIT
3 
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <sys/stat.h>
10 #include "sdb.h"
11 #include "sdb_private.h"
12 
13 static inline SdbKv *next_kv(HtPP *ht, SdbKv *kv) {
14  return (SdbKv *)((char *)kv + ht->opt.elem_size);
15 }
16 
17 #define BUCKET_FOREACH(ht, bt, j, kv) \
18  for ((j) = 0, (kv) = (SdbKv *)(bt)->arr; j < (bt)->count; (j)++, (kv) = next_kv(ht, kv))
19 
20 #define BUCKET_FOREACH_SAFE(ht, bt, j, count, kv) \
21  if ((bt)->arr) \
22  for ((j) = 0, (kv) = (SdbKv *)(bt)->arr, (count) = (ht)->count; \
23  (j) < (bt)->count; \
24  (j) = (count) == (ht)->count ? j + 1 : j, (kv) = (count) == (ht)->count ? next_kv(ht, kv) : kv, (count) = (ht)->count)
25 
26 static inline int nextcas(void) {
27  static ut32 cas = 1;
28  if (!cas) {
29  cas++;
30  }
31  return cas++;
32 }
33 
35 static void *global_user = NULL;
36 
37 RZ_API void sdb_global_hook(SdbHook hook, void *user) {
38  global_hook = hook;
39  global_user = user;
40 }
41 
42 // TODO: use mmap instead of read.. much faster!
44  return sdb_new(NULL, NULL, 0);
45 }
46 
47 RZ_API Sdb *sdb_new(const char *path, const char *name, int lock) {
48  Sdb *s = RZ_NEW0(Sdb);
49  if (!s) {
50  return NULL;
51  }
52  s->db.fd = -1;
53  s->fd = -1;
54  s->refs = 1;
55  if (path && !*path) {
56  path = NULL;
57  }
58  if (name && *name && strcmp(name, "-")) {
59  if (path && *path) {
60  int plen = strlen(path);
61  int nlen = strlen(name);
62  s->dir = malloc(plen + nlen + 2);
63  if (!s->dir) {
64  free(s);
65  return NULL;
66  }
67  memcpy(s->dir, path, plen);
68  s->dir[plen] = '/';
69  memcpy(s->dir + plen + 1, name, nlen + 1);
70  s->path = strdup(path);
71  } else {
72  s->dir = strdup(name);
73  }
74  switch (lock) {
75  case 1:
76  if (!sdb_lock(sdb_lock_file(s->dir))) {
77  goto fail;
78  }
79  break;
80  case 2:
81  if (!sdb_lock_wait(sdb_lock_file(s->dir))) {
82  goto fail;
83  }
84  break;
85  }
86  if (sdb_open(s, s->dir) == -1) {
87  s->last = s->timestamped ? sdb_now() : 0LL;
88  // TODO: must fail if we cant open for write in sync
89  }
90  s->name = strdup(name);
91  } else {
92  s->last = s->timestamped ? sdb_now() : 0LL;
93  s->fd = -1;
94  }
95  s->journal = -1;
96  s->fdump = -1;
97  s->depth = 0;
98  s->ndump = NULL;
99  s->ns = ls_new(); // TODO: should be NULL
100  if (!s->ns) {
101  goto fail;
102  }
103  s->ns->free = NULL;
104  if (!s->ns) {
105  goto fail;
106  }
107  s->ht = sdb_ht_new();
108  s->lock = lock;
109  // if open fails ignore
110  if (global_hook) {
112  }
113  cdb_init(&s->db, s->fd);
114  return s;
115 fail:
116  if (s->fd != -1) {
117  close(s->fd);
118  s->fd = -1;
119  }
120  free(s->dir);
121  free(s->name);
122  free(s->path);
123  free(s);
124  return NULL;
125 }
126 
127 // XXX: this is wrong. stuff not stored in memory is lost
128 RZ_API void sdb_file(Sdb *s, const char *dir) {
129  if (s->lock) {
130  sdb_unlock(sdb_lock_file(s->dir));
131  }
132  free(s->dir);
133  s->dir = (dir && *dir) ? strdup(dir) : NULL;
134  if (s->lock) {
135  sdb_lock(sdb_lock_file(s->dir));
136  }
137 }
138 
139 static bool sdb_merge_cb(void *user, const char *k, const char *v) {
140  sdb_set(user, k, v, 0);
141  return true;
142 }
143 
144 RZ_API bool sdb_merge(Sdb *d, Sdb *s) {
145  return sdb_foreach(s, sdb_merge_cb, d);
146 }
147 
149  if (s) {
150  if (s->db.fd != -1) {
151  sdb_dump_begin(s);
152  while (sdb_dump_hasnext(s)) {
153  return false;
154  }
155  }
156  if (s->ht && s->ht->count > 0) {
157  return false;
158  }
159  }
160  return true;
161 }
162 
164  int count = 0;
165  if (s) {
166  if (s->db.fd != -1) {
167  sdb_dump_begin(s);
168  while (sdb_dump_hasnext(s)) {
169  count++;
170  }
171  }
172  if (s->ht) {
173  count += s->ht->count;
174  }
175  }
176  return count;
177 }
178 
179 static void sdb_fini(Sdb *s, int donull) {
180  if (!s) {
181  return;
182  }
183  sdb_hook_free(s);
184  cdb_free(&s->db);
185  if (s->lock) {
186  sdb_unlock(sdb_lock_file(s->dir));
187  }
189  s->refs = 0;
190  free(s->name);
191  free(s->path);
192  ls_free(s->ns);
193  sdb_ht_free(s->ht);
195  if (s->fd != -1) {
196  close(s->fd);
197  s->fd = -1;
198  }
199  free(s->ndump);
200  free(s->dir);
201  if (donull) {
202  memset(s, 0, sizeof(Sdb));
203  }
204 }
205 
207  if (s && s->ht && s->refs) {
208  s->refs--;
209  if (s->refs < 1) {
210  s->refs = 0;
211  sdb_fini(s, 0);
212  s->ht = NULL;
213  free(s);
214  return true;
215  }
216  }
217  return false;
218 }
219 
220 RZ_API const char *sdb_const_get_len(Sdb *s, const char *key, int *vlen, ut32 *cas) {
221  ut32 pos, len;
222  ut64 now = 0LL;
223  bool found;
224 
225  if (cas) {
226  *cas = 0;
227  }
228  if (vlen) {
229  *vlen = 0;
230  }
231  if (!s || !key) {
232  return NULL;
233  }
234  // TODO: optimize, iterate once
235  size_t keylen = strlen(key);
236 
237  /* search in memory */
238  SdbKv *kv = (SdbKv *)sdb_ht_find_kvp(s->ht, key, &found);
239  if (found) {
240  if (!sdbkv_value(kv) || !*sdbkv_value(kv)) {
241  return NULL;
242  }
243  if (s->timestamped && kv->expire) {
244  if (!now) {
245  now = sdb_now();
246  }
247  if (now > kv->expire) {
248  sdb_unset(s, key, 0);
249  return NULL;
250  }
251  }
252  if (cas) {
253  *cas = kv->cas;
254  }
255  if (vlen) {
256  *vlen = sdbkv_value_len(kv);
257  }
258  return sdbkv_value(kv);
259  }
260  /* search in disk */
261  if (s->fd == -1) {
262  return NULL;
263  }
264  (void)cdb_findstart(&s->db);
265  if (cdb_findnext(&s->db, s->ht->opt.hashfn(key), key, keylen) < 1) {
266  return NULL;
267  }
268  len = cdb_datalen(&s->db);
269  if (len < SDB_CDB_MIN_VALUE || len >= SDB_CDB_MAX_VALUE) {
270  return NULL;
271  }
272  if (vlen) {
273  *vlen = len;
274  }
275  pos = cdb_datapos(&s->db);
276  return s->db.map + pos;
277 }
278 
279 RZ_API const char *sdb_const_get(Sdb *s, const char *key, ut32 *cas) {
280  return sdb_const_get_len(s, key, NULL, cas);
281 }
282 
283 // TODO: add sdb_getf?
284 
285 RZ_API char *sdb_get_len(Sdb *s, const char *key, int *vlen, ut32 *cas) {
286  const char *value = sdb_const_get_len(s, key, vlen, cas);
287  return value ? strdup(value) : NULL;
288 }
289 
290 RZ_API char *sdb_get(Sdb *s, const char *key, ut32 *cas) {
291  return sdb_get_len(s, key, NULL, cas);
292 }
293 
294 RZ_API int sdb_unset(Sdb *s, const char *key, ut32 cas) {
295  return key ? sdb_set(s, key, "", cas) : 0;
296 }
297 
298 /* remove from memory */
299 RZ_API bool sdb_remove(Sdb *s, const char *key, ut32 cas) {
300  return sdb_ht_delete(s->ht, key);
301 }
302 
303 // alias for '-key=str'.. '+key=str' concats
304 RZ_API int sdb_uncat(Sdb *s, const char *key, const char *value, ut32 cas) {
305  // remove 'value' from current key value.
306  // TODO: cas is ignored here
307  int vlen = 0, valen;
308  char *p, *v = sdb_get_len(s, key, &vlen, NULL);
309  int mod = 0;
310  if (!v || !key || !value) {
311  free(v);
312  return 0;
313  }
314  valen = strlen(value);
315  if (valen > 0) {
316  while ((p = strstr(v, value))) {
317  memmove(p, p + valen, strlen(p + valen) + 1);
318  mod = 1;
319  }
320  }
321  if (mod) {
322  sdb_set_owned(s, key, v, 0);
323  } else {
324  free(v);
325  }
326  return 0;
327 }
328 
329 RZ_API int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas) {
330  int kl, vl;
331  const char *p;
332  char *o;
333  if (!s || !key || !*key || !value || !*value) {
334  return 0;
335  }
336  p = sdb_const_get_len(s, key, &kl, 0);
337  if (!p) {
338  return sdb_set(s, key, value, cas);
339  }
340  vl = strlen(value);
341  o = malloc(kl + vl + 1);
342  if (o) {
343  memcpy(o, p, kl);
344  memcpy(o + kl, value, vl + 1);
345  return sdb_set_owned(s, key, o, cas);
346  }
347  return 0;
348 }
349 
350 // set if not defined
351 RZ_API int sdb_add(Sdb *s, const char *key, const char *val, ut32 cas) {
352  if (sdb_exists(s, key)) {
353  return 0;
354  }
355  return sdb_set(s, key, val, cas);
356 }
357 
358 RZ_API bool sdb_exists(Sdb *s, const char *key) {
359  ut32 pos;
360  char ch;
361  bool found;
362  int klen = strlen(key) + 1;
363  if (!s) {
364  return false;
365  }
366  SdbKv *kv = (SdbKv *)sdb_ht_find_kvp(s->ht, key, &found);
367  if (found && kv) {
368  char *v = sdbkv_value(kv);
369  return v && *v;
370  }
371  if (s->fd == -1) {
372  return false;
373  }
374  (void)cdb_findstart(&s->db);
375  if (cdb_findnext(&s->db, sdb_hash(key), key, klen)) {
376  pos = cdb_datapos(&s->db);
377  cdb_read(&s->db, &ch, 1, pos);
378  return ch != 0;
379  }
380  return false;
381 }
382 
383 RZ_API int sdb_open(Sdb *s, const char *file) {
384  struct stat st;
385  if (!s) {
386  return -1;
387  }
388  if (file) {
389  if (s->fd != -1) {
390  close(s->fd);
391  s->fd = -1;
392  }
393  s->fd = open(file, O_RDONLY | O_BINARY);
394  if (file != s->dir) {
395  free(s->dir);
396  s->dir = strdup(file);
397  s->path = NULL; // TODO: path is important
398  }
399  }
400  s->last = 0LL;
401  if (s->fd != -1 && fstat(s->fd, &st) != -1) {
402  if ((S_IFREG & st.st_mode) != S_IFREG) {
403  eprintf("Database must be a file\n");
404  close(s->fd);
405  s->fd = -1;
406  return -1;
407  }
408  s->last = st.st_mtime;
409  }
410  if (s->fd != -1) {
411  cdb_init(&s->db, s->fd);
412  }
413  return s->fd;
414 }
415 
417  if (s) {
418  if (s->fd != -1) {
419  if (s->db.fd != -1 && s->db.fd == s->fd) {
420  /* close db fd as well */
421  s->db.fd = -1;
422  }
423  close(s->fd);
424  s->fd = -1;
425  }
426  if (s->dir) {
427  free(s->dir);
428  s->dir = NULL;
429  }
430  }
431 }
432 
434  if (!s) {
435  return;
436  }
437  /* ignore disk cache, file is not removed, but we will ignore
438  * its values when syncing again */
439  sdb_close(s);
440  /* empty memory hashtable */
441  sdb_ht_free(s->ht);
442  s->ht = sdb_ht_new();
443 }
444 
445 static char lastChar(const char *str) {
446  int len = strlen(str);
447  return str[(len > 0) ? len - 1 : 0];
448 }
449 
450 static bool match(const char *str, const char *expr) {
451  bool startsWith = *expr == '^';
452  bool endsWith = lastChar(expr) == '$';
453  if (startsWith && endsWith) {
454  return strlen(str) == strlen(expr) - 2 &&
455  !strncmp(str, expr + 1, strlen(expr) - 2);
456  }
457  if (startsWith) {
458  return !strncmp(str, expr + 1, strlen(expr) - 1);
459  }
460  if (endsWith) {
461  int alen = strlen(str);
462  int blen = strlen(expr) - 1;
463  if (alen <= blen) {
464  return false;
465  }
466  const char *a = str + strlen(str) - blen;
467  return (!strncmp(a, expr, blen));
468  }
469  return strstr(str, expr);
470 }
471 
472 RZ_API bool sdbkv_match(SdbKv *kv, const char *expr) {
473  // TODO: add syntax to negate condition
474  // TODO: add syntax to OR k/v instead of AND
475  // [^]str[$]=[^]str[$]
476  const char *eq = strchr(expr, '=');
477  if (eq) {
478  char *e = strdup(expr);
479  char *ep = e + (eq - expr);
480  *ep++ = 0;
481  bool res = !*e || match(sdbkv_key(kv), e);
482  bool res2 = !*ep || match(sdbkv_value(kv), ep);
483  free(e);
484  return res && res2;
485  }
486  return match(sdbkv_key(kv), expr);
487 }
488 
489 RZ_API SdbKv *sdbkv_new(const char *k, const char *v) {
490  return sdbkv_new2(k, strlen(k), v, strlen(v));
491 }
492 
493 RZ_API SdbKv *sdbkv_new2(const char *k, int kl, const char *v, int vl) {
494  SdbKv *kv;
495  if (!v) {
496  vl = 0;
497  }
498  kv = RZ_NEW0(SdbKv);
499  kv->base.key_len = kl;
500  kv->base.key = malloc(kv->base.key_len + 1);
501  if (!kv->base.key) {
502  free(kv);
503  return NULL;
504  }
505  memcpy(kv->base.key, k, kv->base.key_len + 1);
506  kv->base.value_len = vl;
507  if (vl) {
508  kv->base.value = malloc(vl + 1);
509  if (!kv->base.value) {
510  free(kv->base.key);
511  free(kv);
512  return NULL;
513  }
514  memcpy(kv->base.value, v, vl + 1);
515  } else {
516  kv->base.value = NULL;
517  kv->base.value_len = 0;
518  }
519  kv->cas = nextcas();
520  kv->expire = 0LL;
521  return kv;
522 }
523 
525  if (kv) {
526  free(sdbkv_key(kv));
527  free(sdbkv_value(kv));
528  RZ_FREE(kv);
529  }
530 }
531 
532 static ut32 sdb_set_internal(Sdb *s, const char *key, char *val, int owned, ut32 cas) {
533  ut32 vlen, klen;
534  SdbKv *kv;
535  bool found;
536  if (!s || !key) {
537  return 0;
538  }
539  if (!val) {
540  if (owned) {
541  val = strdup("");
542  } else {
543  val = "";
544  }
545  }
546  // XXX strlen computed twice.. because of check_*()
547  klen = strlen(key);
548  vlen = strlen(val);
549  if (s->journal != -1) {
551  }
552  cdb_findstart(&s->db);
553  kv = sdb_ht_find_kvp(s->ht, key, &found);
554  if (found && sdbkv_value(kv)) {
555  if (cdb_findnext(&s->db, sdb_hash(key), key, klen)) {
556  if (cas && kv->cas != cas) {
557  if (owned) {
558  free(val);
559  }
560  return 0;
561  }
562  if (vlen == sdbkv_value_len(kv) && !strcmp(sdbkv_value(kv), val)) {
563  sdb_hook_call(s, key, val);
564  return kv->cas;
565  }
566  kv->cas = cas = nextcas();
567  if (owned) {
568  kv->base.value_len = vlen;
569  free(kv->base.value);
570  kv->base.value = val; // owned
571  } else {
572  if ((ut32)vlen > kv->base.value_len) {
573  free(kv->base.value);
574  kv->base.value = malloc(vlen + 1);
575  }
576  memcpy(kv->base.value, val, vlen + 1);
577  kv->base.value_len = vlen;
578  }
579  } else {
580  sdb_ht_delete(s->ht, key);
581  }
582  sdb_hook_call(s, key, val);
583  return cas;
584  }
585  // empty values are also stored
586  // TODO store only the ones that are in the CDB
587  if (owned) {
588  kv = sdbkv_new2(key, klen, NULL, 0);
589  if (kv) {
590  kv->base.value = val;
591  kv->base.value_len = vlen;
592  }
593  } else {
594  kv = sdbkv_new2(key, klen, val, vlen);
595  }
596  if (kv) {
597  ut32 cas = kv->cas = nextcas();
598  sdb_ht_insert_kvp(s->ht, kv, true /*update*/);
599  free(kv);
600  sdb_hook_call(s, key, val);
601  return cas;
602  }
603  // kv set failed, no need to callback sdb_hook_call (s, key, val);
604  return 0;
605 }
606 
607 RZ_API int sdb_set_owned(Sdb *s, const char *key, char *val, ut32 cas) {
608  return sdb_set_internal(s, key, val, 1, cas);
609 }
610 
611 RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas) {
612  return sdb_set_internal(s, key, (char *)val, 0, cas);
613 }
614 
615 static bool sdb_foreach_list_cb(void *user, const char *k, const char *v) {
616  SdbList *list = (SdbList *)user;
617  SdbKv *kv = RZ_NEW0(SdbKv);
618  /* seems like some k/v are constructed in the stack and cant be used after returning */
619  kv->base.key = strdup(k);
620  kv->base.value = strdup(v);
621  ls_append(list, kv);
622  return 1;
623 }
624 
625 static int __cmp_asc(const void *a, const void *b) {
626  const SdbKv *ka = a, *kb = b;
627  return strcmp(sdbkv_key(ka), sdbkv_key(kb));
628 }
629 
633  if (sorted) {
635  }
636  return list;
637 }
638 
642  void *user;
643 };
644 
645 static bool sdb_foreach_list_filter_cb(void *user, const char *k, const char *v) {
646  struct foreach_list_filter_t *u = (struct foreach_list_filter_t *)user;
647  SdbList *list = u->list;
648  SdbKv *kv = NULL;
649 
650  if (!u->filter || u->filter(u->user, k, v)) {
651  kv = RZ_NEW0(SdbKv);
652  if (!kv) {
653  goto err;
654  }
655  kv->base.key = strdup(k);
656  kv->base.value = strdup(v);
657  if (!kv->base.key || !kv->base.value) {
658  goto err;
659  }
660  ls_append(list, kv);
661  }
662  return true;
663 err:
664  sdbkv_free(kv);
665  return false;
666 }
667 
669  struct foreach_list_filter_t u;
671 
672  if (!list) {
673  return NULL;
674  }
675  u.filter = filter;
676  u.list = list;
677  u.user = user;
679  if (sorted) {
681  }
682  return list;
683 }
684 
686  return sdb_foreach_list_filter_user(s, filter, sorted, NULL);
687 }
688 
689 typedef struct {
690  const char *expr;
692  bool single;
694 
695 static bool sdb_foreach_match_cb(void *user, const char *k, const char *v) {
696  _match_sdb_user *o = (_match_sdb_user *)user;
697  SdbKv tkv = { .base.key = (char *)k, .base.value = (char *)v };
698  if (sdbkv_match(&tkv, o->expr)) {
699  SdbKv *kv = RZ_NEW0(SdbKv);
700  kv->base.key = strdup(k);
701  kv->base.value = strdup(v);
702  ls_append(o->list, kv);
703  if (o->single) {
704  return false;
705  }
706  }
707  return true;
708 }
709 
710 RZ_API SdbList *sdb_foreach_match(Sdb *s, const char *expr, bool single) {
712  _match_sdb_user o = { expr, list, single };
714  return list;
715 }
716 
717 static int getbytes(Sdb *s, char *b, int len) {
718  if (!cdb_read(&s->db, b, len, s->pos)) {
719  return -1;
720  }
721  s->pos += len;
722  return len;
723 }
724 
725 static bool sdb_foreach_end(Sdb *s, bool result) {
726  s->depth--;
727  return result;
728 }
729 
730 static bool sdb_foreach_cdb(Sdb *s, SdbForeachCallback cb, SdbForeachCallback cb2, void *user) {
731  char *v = NULL;
732  char k[SDB_CDB_MAX_KEY] = { 0 };
733  bool found;
734  sdb_dump_begin(s);
735  while (sdb_dump_dupnext(s, k, &v, NULL)) {
736  SdbKv *kv = sdb_ht_find_kvp(s->ht, k, &found);
737  if (found) {
738  free(v);
739  if (kv && sdbkv_key(kv) && sdbkv_value(kv)) {
740  if (!cb(user, sdbkv_key(kv), sdbkv_value(kv))) {
741  return false;
742  }
743  if (cb2 && !cb2(user, k, sdbkv_value(kv))) {
744  return false;
745  }
746  }
747  } else {
748  if (!cb(user, k, v)) {
749  free(v);
750  return false;
751  }
752  free(v);
753  }
754  }
755  return true;
756 }
757 
759  if (!s) {
760  return false;
761  }
762  s->depth++;
763  bool result = sdb_foreach_cdb(s, cb, NULL, user);
764  if (!result) {
765  return sdb_foreach_end(s, false);
766  }
767 
768  ut32 i;
769  for (i = 0; i < s->ht->size; ++i) {
770  HtPPBucket *bt = &s->ht->table[i];
771  SdbKv *kv;
772  ut32 j, count;
773 
774  BUCKET_FOREACH_SAFE(s->ht, bt, j, count, kv) {
775  if (kv && sdbkv_value(kv) && *sdbkv_value(kv)) {
776  if (!cb(user, sdbkv_key(kv), sdbkv_value(kv))) {
777  return sdb_foreach_end(s, false);
778  }
779  }
780  }
781  }
782  return sdb_foreach_end(s, true);
783 }
784 
785 static bool _insert_into_disk(void *user, const char *key, const char *value) {
786  Sdb *s = (Sdb *)user;
787  if (s) {
789  return true;
790  }
791  return false;
792 }
793 
794 static bool _remove_afer_insert(void *user, const char *k, const char *v) {
795  Sdb *s = (Sdb *)user;
796  if (s) {
797  sdb_ht_delete(s->ht, k);
798  return true;
799  }
800  return false;
801 }
802 
804  bool result;
805  ut32 i;
806 
807  if (!s || !sdb_disk_create(s)) {
808  return false;
809  }
811  if (!result) {
812  return false;
813  }
814 
815  /* append new keyvalues */
816  for (i = 0; i < s->ht->size; ++i) {
817  HtPPBucket *bt = &s->ht->table[i];
818  SdbKv *kv;
819  ut32 j, count;
820 
821  BUCKET_FOREACH_SAFE(s->ht, bt, j, count, kv) {
822  if (sdbkv_key(kv) && sdbkv_value(kv) && *sdbkv_value(kv) && !kv->expire) {
823  if (sdb_disk_insert(s, sdbkv_key(kv), sdbkv_value(kv))) {
824  sdb_remove(s, sdbkv_key(kv), 0);
825  }
826  }
827  }
828  }
831  // TODO: sdb_reset memory state?
832  return true;
833 }
834 
836  if (s->fd != -1) {
837  s->pos = sizeof(((struct cdb_make *)0)->final);
838  seek_set(s->fd, s->pos);
839  } else {
840  s->pos = 0;
841  }
842 }
843 
845  ut32 k, v;
846  if (!cdb_getkvlen(&s->db, &k, &v, s->pos)) {
847  return false;
848  }
849  if (k < 1 || v < 1) {
850  return false;
851  }
852  s->pos += k + v + 4;
853  return true;
854 }
855 
856 RZ_API bool sdb_stats(Sdb *s, ut32 *disk, ut32 *mem) {
857  if (!s) {
858  return false;
859  }
860  if (disk) {
861  ut32 count = 0;
862  if (s->fd != -1) {
863  sdb_dump_begin(s);
864  while (sdb_dump_hasnext(s)) {
865  count++;
866  }
867  }
868  *disk = count;
869  }
870  if (mem) {
871  *mem = s->ht->count;
872  }
873  return disk || mem;
874 }
875 
876 // TODO: make it static? internal api?
877 RZ_API bool sdb_dump_dupnext(Sdb *s, char *key, char **value, int *_vlen) {
878  ut32 vlen = 0, klen = 0;
879  if (value) {
880  *value = NULL;
881  }
882  if (_vlen) {
883  *_vlen = 0;
884  }
885  if (!cdb_getkvlen(&s->db, &klen, &vlen, s->pos)) {
886  return false;
887  }
888  s->pos += 4;
889  if (klen < 1 || vlen < 1) {
890  return false;
891  }
892  if (_vlen) {
893  *_vlen = vlen;
894  }
895  if (key) {
896  key[0] = 0;
897  if (klen > SDB_CDB_MIN_KEY && klen < SDB_CDB_MAX_KEY) {
898  if (getbytes(s, key, klen) == -1) {
899  return 0;
900  }
901  key[klen] = 0;
902  }
903  }
904  if (value) {
905  *value = 0;
906  if (vlen < SDB_CDB_MAX_VALUE) {
907  *value = malloc(vlen + 10);
908  if (!*value) {
909  return false;
910  }
911  if (getbytes(s, *value, vlen) == -1) {
912  free(*value);
913  *value = NULL;
914  return false;
915  }
916  (*value)[vlen] = 0;
917  }
918  }
919  return true;
920 }
921 
922 static inline ut64 parse_expire(ut64 e) {
923  const ut64 month = 30 * 24 * 60 * 60;
924  if (e > 0 && e < month) {
925  e += sdb_now();
926  }
927  return e;
928 }
929 
930 RZ_API bool sdb_expire_set(Sdb *s, const char *key, ut64 expire, ut32 cas) {
931  char *buf;
932  ut32 pos, len;
933  SdbKv *kv;
934  bool found;
935  s->timestamped = true;
936  if (!key) {
937  s->expire = parse_expire(expire);
938  return true;
939  }
940  kv = (SdbKv *)sdb_ht_find_kvp(s->ht, key, &found);
941  if (found && kv) {
942  if (*sdbkv_value(kv)) {
943  if (!cas || cas == kv->cas) {
944  kv->expire = parse_expire(expire);
945  return true;
946  }
947  }
948  return false;
949  }
950  if (s->fd == -1) {
951  return false;
952  }
953  (void)cdb_findstart(&s->db);
954  if (!cdb_findnext(&s->db, sdb_hash(key), key, strlen(key) + 1)) {
955  return false;
956  }
957  pos = cdb_datapos(&s->db);
958  len = cdb_datalen(&s->db);
959  if (len < 1 || len >= INT32_MAX) {
960  return false;
961  }
962  if (!(buf = calloc(1, len + 1))) {
963  return false;
964  }
965  cdb_read(&s->db, buf, len, pos);
966  buf[len] = 0;
967  sdb_set_owned(s, key, buf, cas);
968  return sdb_expire_set(s, key, expire, cas); // recursive
969 }
970 
971 RZ_API ut64 sdb_expire_get(Sdb *s, const char *key, ut32 *cas) {
972  bool found = false;
973  SdbKv *kv = (SdbKv *)sdb_ht_find_kvp(s->ht, key, &found);
974  if (found && kv && *sdbkv_value(kv)) {
975  if (cas) {
976  *cas = kv->cas;
977  }
978  return kv->expire;
979  }
980  return 0LL;
981 }
982 
983 RZ_API bool sdb_hook(Sdb *s, SdbHook cb, void *user) {
984  int i = 0;
985  SdbHook hook;
986  SdbListIter *iter;
987  if (s->hooks) {
988  ls_foreach (s->hooks, iter, hook) {
989  if (!(i % 2) && (hook == cb)) {
990  return false;
991  }
992  i++;
993  }
994  } else {
995  s->hooks = ls_new();
996  s->hooks->free = NULL;
997  }
998  ls_append(s->hooks, (void *)cb);
999  ls_append(s->hooks, user);
1000  return true;
1001 }
1002 
1004  int i = 0;
1005  SdbHook hook;
1006  SdbListIter *iter, *iter2;
1007  ls_foreach (s->hooks, iter, hook) {
1008  if (!(i % 2) && (hook == h)) {
1009  iter2 = iter->n;
1010  ls_delete(s->hooks, iter);
1011  ls_delete(s->hooks, iter2);
1012  return true;
1013  }
1014  i++;
1015  }
1016  return false;
1017 }
1018 
1019 RZ_API int sdb_hook_call(Sdb *s, const char *k, const char *v) {
1020  SdbListIter *iter;
1021  SdbHook hook;
1022  int i = 0;
1023  if (s->timestamped && s->last) {
1024  s->last = sdb_now();
1025  }
1026  ls_foreach (s->hooks, iter, hook) {
1027  if (!(i % 2) && k && iter->n) {
1028  void *u = iter->n->data;
1029  hook(s, u, k, v);
1030  }
1031  i++;
1032  }
1033  return i >> 1;
1034 }
1035 
1037  ls_free(s->hooks);
1038  s->hooks = NULL;
1039 }
1040 
1042  s->options = options;
1043  if (options & SDB_OPTION_SYNC) {
1044  // sync on every query
1045  }
1046  if (options & SDB_OPTION_JOURNAL) {
1047  // sync on every query
1049  // load journaling if exists
1052  } else {
1054  }
1055  if (options & SDB_OPTION_NOSTAMP) {
1056  // sync on every query
1057  s->last = 0LL;
1058  }
1059  if (options & SDB_OPTION_FS) {
1060  // have access to fs (handle '.' or not in query)
1061  }
1062 }
1063 
1065  sdb_fini(s, 1);
1066  return sdb_disk_unlink(s);
1067 }
1068 
1070  if (s && f) {
1071  f->refs = s->refs;
1072  sdb_fini(s, 1);
1073  *s = *f;
1074  free(f);
1075  }
1076 }
1077 
1078 static bool copy_foreach_cb(void *user, const char *k, const char *v) {
1079  Sdb *dst = user;
1080  sdb_set(dst, k, v, 0);
1081  return true;
1082 }
1083 
1086  SdbListIter *it;
1087  SdbNs *ns;
1088  ls_foreach (src->ns, it, ns) {
1089  sdb_copy(ns->sdb, sdb_ns(dst, ns->name, true));
1090  }
1091 }
1092 
1093 typedef struct {
1095  const char *key;
1097 
1098 static bool unset_cb(void *user, const char *k, const char *v) {
1099  UnsetCallbackData *ucd = user;
1100  if (sdb_match(k, ucd->key)) {
1101  sdb_unset(ucd->sdb, k, 0);
1102  }
1103  return true;
1104 }
1105 
1106 RZ_API int sdb_unset_like(Sdb *s, const char *k) {
1107  UnsetCallbackData ucd = { s, k };
1108  return sdb_foreach(s, unset_cb, &ucd);
1109 }
1110 
1111 typedef struct {
1113  const char *key;
1114  const char *val;
1116  const char **array;
1120 
1121 static bool like_cb(void *user, const char *k, const char *v) {
1122  LikeCallbackData *lcd = user;
1123  if (!user) {
1124  return false;
1125  }
1126  if (k && lcd->key && !sdb_match(k, lcd->key)) {
1127  return true;
1128  }
1129  if (v && lcd->val && !sdb_match(v, lcd->val)) {
1130  return true;
1131  }
1132  if (lcd->array) {
1133  int idx = lcd->array_index;
1134  int newsize = lcd->array_size + sizeof(char *) * 2;
1135  const char **newarray = (const char **)realloc((void *)lcd->array, newsize);
1136  if (!newarray) {
1137  return false;
1138  }
1139  lcd->array = newarray;
1140  lcd->array_size = newsize;
1141  // concatenate in array
1142  lcd->array[idx] = k;
1143  lcd->array[idx + 1] = v;
1144  lcd->array[idx + 2] = NULL;
1145  lcd->array[idx + 3] = NULL;
1146  lcd->array_index = idx + 2;
1147  } else {
1148  if (lcd->cb) {
1149  lcd->cb(lcd->sdb, k, v);
1150  }
1151  }
1152  return true;
1153 }
1154 
1155 RZ_API char **sdb_like(Sdb *s, const char *k, const char *v, SdbForeachCallback cb) {
1156  LikeCallbackData lcd = { s, k, v, cb, NULL, 0, 0 };
1157  if (cb) {
1158  sdb_foreach(s, like_cb, &lcd);
1159  return NULL;
1160  }
1161  if (k && !*k) {
1162  lcd.key = NULL;
1163  }
1164  if (v && !*v) {
1165  lcd.val = NULL;
1166  }
1167  lcd.array_size = sizeof(char *) * 2;
1168  lcd.array = calloc(lcd.array_size, 1);
1169  if (!lcd.array) {
1170  return NULL;
1171  }
1172  lcd.array_index = 0;
1173  sdb_foreach(s, like_cb, &lcd);
1174  if (lcd.array_index == 0) {
1175  free((void *)lcd.array);
1176  return NULL;
1177  }
1178  return (char **)lcd.array;
1179 }
size_t len
Definition: 6502dis.c:15
#define e(frag)
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
ut16 val
Definition: armass64_const.h:6
static bool err
Definition: armass.c:435
static RzNumCalcValue expr(RzNum *, RzNumCalc *, int)
Definition: calc.c:167
bool cdb_init(struct cdb *c, int fd)
Definition: cdb.c:51
bool cdb_getkvlen(struct cdb *c, ut32 *klen, ut32 *vlen, ut32 pos)
Definition: cdb.c:15
void cdb_free(struct cdb *c)
Definition: cdb.c:30
bool cdb_read(struct cdb *c, char *buf, ut32 len, ut32 pos)
Definition: cdb.c:89
void cdb_findstart(struct cdb *c)
Definition: cdb.c:42
int cdb_findnext(struct cdb *c, ut32 u, const char *key, ut32 len)
Definition: cdb.c:132
#define cdb_datalen(c)
Definition: cdb.h:42
#define cdb_datapos(c)
Definition: cdb.h:41
static int value
Definition: cmd_api.c:93
#define O_BINARY
Definition: cpipe.c:13
#define RZ_API
#define NULL
Definition: cris-opc.c:27
int mod(int a, int b)
Definition: crypto_rot.c:8
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset fstat
Definition: sflib.h:107
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
uint32_t ut32
RZ_API bool sdb_disk_insert(Sdb *s, const char *key, const char *val)
Definition: disk.c:67
RZ_API bool sdb_disk_unlink(Sdb *s)
Definition: disk.c:121
RZ_API bool sdb_disk_finish(Sdb *s)
Definition: disk.c:79
RZ_API bool sdb_disk_create(Sdb *s)
Definition: disk.c:17
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
voidpf void * buf
Definition: ioapi.h:138
RZ_API bool sdb_journal_open(Sdb *s)
Definition: journal.c:23
RZ_API int sdb_journal_load(Sdb *s)
Definition: journal.c:38
RZ_API bool sdb_journal_clear(Sdb *s)
Definition: journal.c:96
RZ_API bool sdb_journal_log(Sdb *s, const char *key, const char *val)
Definition: journal.c:81
RZ_API bool sdb_journal_close(Sdb *s)
Definition: journal.c:13
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
void * mem
Definition: libc.cpp:91
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static void list(RzEgg *egg)
Definition: rz-gg.c:52
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
RZ_API void sdb_unlock(const char *s)
Definition: lock.c:60
RZ_API bool sdb_lock(const char *s)
Definition: lock.c:29
RZ_API int sdb_lock_wait(const char *s)
Definition: lock.c:50
RZ_API const char * sdb_lock_file(const char *f)
Definition: lock.c:14
RZ_API SdbList * ls_new(void)
Definition: ls.c:16
RZ_API SdbListIter * ls_append(SdbList *list, void *data)
Definition: ls.c:200
RZ_API void ls_free(SdbList *list)
Definition: ls.c:191
RZ_API bool ls_sort(SdbList *list, SdbListComparator cmp)
Definition: ls.c:119
RZ_API void ls_delete(SdbList *list, SdbListIter *iter)
Definition: ls.c:133
RZ_API SdbList * ls_newf(SdbListFree freefn)
Definition: ls.c:8
void(* SdbListFree)(void *ptr)
Definition: ls.h:14
#define ls_foreach(list, it, pos)
Definition: ls.h:31
char * dst
Definition: lz4.h:724
RZ_API bool sdb_match(const char *str, const char *glob)
Definition: match.c:95
int idx
Definition: setup.py:197
RZ_API void sdb_ns_free_all(Sdb *s)
Definition: ns.c:74
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
static bool filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char *data, char *str, int len, bool big_endian)
Definition: filter.c:185
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
RZ_API bool sdb_dump_dupnext(Sdb *s, char *key, char **value, int *_vlen)
Definition: sdb.c:877
RZ_API SdbKv * sdbkv_new2(const char *k, int kl, const char *v, int vl)
Definition: sdb.c:493
RZ_API Sdb * sdb_new(const char *path, const char *name, int lock)
Definition: sdb.c:47
RZ_API void sdb_file(Sdb *s, const char *dir)
Definition: sdb.c:128
static bool sdb_merge_cb(void *user, const char *k, const char *v)
Definition: sdb.c:139
static int getbytes(Sdb *s, char *b, int len)
Definition: sdb.c:717
RZ_API bool sdb_dump_hasnext(Sdb *s)
Definition: sdb.c:844
static bool _insert_into_disk(void *user, const char *key, const char *value)
Definition: sdb.c:785
RZ_API int sdb_set_owned(Sdb *s, const char *key, char *val, ut32 cas)
Definition: sdb.c:607
static bool sdb_foreach_cdb(Sdb *s, SdbForeachCallback cb, SdbForeachCallback cb2, void *user)
Definition: sdb.c:730
RZ_API bool sdb_isempty(Sdb *s)
Definition: sdb.c:148
static bool copy_foreach_cb(void *user, const char *k, const char *v)
Definition: sdb.c:1078
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
static ut32 sdb_set_internal(Sdb *s, const char *key, char *val, int owned, ut32 cas)
Definition: sdb.c:532
static bool sdb_foreach_end(Sdb *s, bool result)
Definition: sdb.c:725
RZ_API void sdb_close(Sdb *s)
Definition: sdb.c:416
static bool match(const char *str, const char *expr)
Definition: sdb.c:450
RZ_API ut64 sdb_expire_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:971
RZ_API void sdb_drain(Sdb *s, Sdb *f)
Definition: sdb.c:1069
RZ_API Sdb * sdb_new0(void)
Definition: sdb.c:43
RZ_API int sdb_add(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:351
RZ_API char * sdb_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:290
RZ_API bool sdb_unhook(Sdb *s, SdbHook h)
Definition: sdb.c:1003
RZ_API char ** sdb_like(Sdb *s, const char *k, const char *v, SdbForeachCallback cb)
Definition: sdb.c:1155
RZ_API bool sdb_remove(Sdb *s, const char *key, ut32 cas)
Definition: sdb.c:299
RZ_API char * sdb_get_len(Sdb *s, const char *key, int *vlen, ut32 *cas)
Definition: sdb.c:285
RZ_API SdbList * sdb_foreach_match(Sdb *s, const char *expr, bool single)
Definition: sdb.c:710
RZ_API bool sdb_merge(Sdb *d, Sdb *s)
Definition: sdb.c:144
RZ_API bool sdb_free(Sdb *s)
Definition: sdb.c:206
static bool unset_cb(void *user, const char *k, const char *v)
Definition: sdb.c:1098
RZ_API int sdb_hook_call(Sdb *s, const char *k, const char *v)
Definition: sdb.c:1019
static SdbKv * next_kv(HtPP *ht, SdbKv *kv)
Definition: sdb.c:13
RZ_API int sdb_count(Sdb *s)
Definition: sdb.c:163
RZ_API void sdb_reset(Sdb *s)
Definition: sdb.c:433
RZ_API SdbList * sdb_foreach_list_filter_user(Sdb *s, SdbForeachCallback filter, bool sorted, void *user)
Definition: sdb.c:668
RZ_API const char * sdb_const_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:279
RZ_API void sdb_copy(Sdb *src, Sdb *dst)
Definition: sdb.c:1084
static char lastChar(const char *str)
Definition: sdb.c:445
static void * global_user
Definition: sdb.c:35
RZ_API bool sdb_foreach(Sdb *s, SdbForeachCallback cb, void *user)
Definition: sdb.c:758
RZ_API bool sdb_stats(Sdb *s, ut32 *disk, ut32 *mem)
Definition: sdb.c:856
RZ_API bool sdb_unlink(Sdb *s)
Definition: sdb.c:1064
RZ_API int sdb_uncat(Sdb *s, const char *key, const char *value, ut32 cas)
Definition: sdb.c:304
static bool sdb_foreach_list_filter_cb(void *user, const char *k, const char *v)
Definition: sdb.c:645
static bool sdb_foreach_match_cb(void *user, const char *k, const char *v)
Definition: sdb.c:695
RZ_API SdbList * sdb_foreach_list_filter(Sdb *s, SdbForeachCallback filter, bool sorted)
Definition: sdb.c:685
RZ_API int sdb_open(Sdb *s, const char *file)
Definition: sdb.c:383
static int __cmp_asc(const void *a, const void *b)
Definition: sdb.c:625
RZ_API int sdb_unset_like(Sdb *s, const char *k)
Definition: sdb.c:1106
static SdbHook global_hook
Definition: sdb.c:34
RZ_API bool sdbkv_match(SdbKv *kv, const char *expr)
Definition: sdb.c:472
RZ_API int sdb_unset(Sdb *s, const char *key, ut32 cas)
Definition: sdb.c:294
RZ_API SdbList * sdb_foreach_list(Sdb *s, bool sorted)
Definition: sdb.c:630
static bool sdb_foreach_list_cb(void *user, const char *k, const char *v)
Definition: sdb.c:615
RZ_API void sdbkv_free(SdbKv *kv)
Definition: sdb.c:524
RZ_API void sdb_hook_free(Sdb *s)
Definition: sdb.c:1036
static bool like_cb(void *user, const char *k, const char *v)
Definition: sdb.c:1121
RZ_API int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas)
Definition: sdb.c:329
RZ_API void sdb_dump_begin(Sdb *s)
Definition: sdb.c:835
RZ_API bool sdb_hook(Sdb *s, SdbHook cb, void *user)
Definition: sdb.c:983
#define BUCKET_FOREACH_SAFE(ht, bt, j, count, kv)
Definition: sdb.c:20
RZ_API bool sdb_expire_set(Sdb *s, const char *key, ut64 expire, ut32 cas)
Definition: sdb.c:930
static int nextcas(void)
Definition: sdb.c:26
static bool _remove_afer_insert(void *user, const char *k, const char *v)
Definition: sdb.c:794
static void sdb_fini(Sdb *s, int donull)
Definition: sdb.c:179
RZ_API void sdb_global_hook(SdbHook hook, void *user)
Definition: sdb.c:37
RZ_API const char * sdb_const_get_len(Sdb *s, const char *key, int *vlen, ut32 *cas)
Definition: sdb.c:220
RZ_API bool sdb_exists(Sdb *s, const char *key)
Definition: sdb.c:358
static ut64 parse_expire(ut64 e)
Definition: sdb.c:922
RZ_API bool sdb_sync(Sdb *s)
Definition: sdb.c:803
RZ_API void sdb_config(Sdb *s, int options)
Definition: sdb.c:1041
RZ_API SdbKv * sdbkv_new(const char *k, const char *v)
Definition: sdb.c:489
#define SDB_OPTION_SYNC
Definition: sdb.h:55
#define SDB_OPTION_FS
Definition: sdb.h:57
bool(* SdbForeachCallback)(void *user, const char *k, const char *v)
Definition: sdb.h:115
RZ_API ut64 sdb_now(void)
Definition: util.c:211
#define SDB_OPTION_JOURNAL
Definition: sdb.h:58
#define SDB_CDB_MAX_VALUE
Definition: sdb.h:19
#define SDB_CDB_MIN_KEY
Definition: sdb.h:20
void(* SdbHook)(Sdb *s, void *user, const char *k, const char *v)
Definition: sdb.h:308
RZ_API ut32 sdb_hash(const char *key)
Definition: util.c:22
#define SDB_CDB_MAX_KEY
Definition: sdb.h:21
#define SDB_OPTION_NOSTAMP
Definition: sdb.h:56
static int seek_set(int fd, off_t pos)
Definition: sdb_private.h:21
RZ_API SdbKv * sdb_ht_find_kvp(HtPP *ht, const char *key, bool *found)
Definition: sdbht.c:55
RZ_API HtPP * sdb_ht_new(void)
Definition: sdbht.c:11
RZ_API void sdb_ht_free(HtPP *ht)
Definition: sdbht.c:63
RZ_API bool sdb_ht_insert_kvp(HtPP *ht, SdbKv *kvp, bool update)
Definition: sdbht.c:47
RZ_API bool sdb_ht_delete(HtPP *ht, const char *key)
Definition: sdbht.c:67
static char * sdbkv_key(const SdbKv *kv)
Definition: sdbht.h:21
static ut32 sdbkv_value_len(const SdbKv *kv)
Definition: sdbht.h:33
static char * sdbkv_value(const SdbKv *kv)
Definition: sdbht.h:25
#define O_RDONLY
Definition: sftypes.h:486
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define a(i)
Definition: sha256.c:41
#define h(i)
Definition: sha256.c:48
#define INT32_MAX
Sdb * sdb
Definition: sdb.c:1112
int array_size
Definition: sdb.c:1118
const char * val
Definition: sdb.c:1114
SdbForeachCallback cb
Definition: sdb.c:1115
int array_index
Definition: sdb.c:1117
const char ** array
Definition: sdb.c:1116
const char * key
Definition: sdb.c:1113
const char * key
Definition: sdb.c:1095
const char * expr
Definition: sdb.c:690
SdbList * list
Definition: sdb.c:691
bool single
Definition: sdb.c:692
Definition: gzappend.c:170
SdbList * list
Definition: sdb.c:641
SdbForeachCallback filter
Definition: sdb.c:640
Definition: ls.h:17
Definition: ls.h:22
Definition: z80asm.h:102
Definition: sdbht.h:14
HtPPKv base
Definition: sdbht.h:16
ut64 expire
Definition: sdbht.h:18
ut32 cas
Definition: sdbht.h:17
Definition: sdb.h:88
char * name
Definition: sdb.h:89
Sdb * sdb
Definition: sdb.h:91
Definition: sdb.h:63
Definition: sftypes.h:80
int pos
Definition: main.c:11
#define fail(test)
Definition: tests.h:29
static void lock(volatile int *lk)
Definition: malloc.c:61
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * cb[]
Definition: z80_tab.h:176