Rizin
unix-like reverse engineering framework and cli tools
main.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: MIT
3 
4 #include <signal.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <fcntl.h>
8 #include "sdb.h"
9 #include "sdb_private.h"
10 
11 #define MODE_ZERO '0'
12 #define MODE_DFLT 0
13 
14 static int save = 0;
15 static Sdb *s = NULL;
17 
18 static void terminate(RZ_UNUSED int sig) {
19  if (!s) {
20  return;
21  }
22  if (save && !sdb_sync(s)) {
23  sdb_free(s);
24  s = NULL;
25  exit(1);
26  }
27  sdb_free(s);
28  exit(sig < 2 ? sig : 0);
29 }
30 
31 static void write_null(void) {
32  write_(1, "", 1);
33 }
34 
35 #define BS 128
36 
37 static char *slurp(FILE *f, size_t *sz) {
38  int blocksize = BS;
39  static int bufsize = BS;
40  static char *next = NULL;
41  static size_t nextlen = 0;
42  size_t len, rr, rr2;
43  char *tmp, *buf = NULL;
44  if (sz) {
45  *sz = 0;
46  }
47  if (!sz) {
48  /* this is faster but have limits */
49  /* run test/add10k.sh script to benchmark */
50  const int buf_size = 96096;
51 
52  buf = calloc(1, buf_size);
53  if (!buf) {
54  return NULL;
55  }
56 
57  if (!fgets(buf, buf_size, f)) {
58  free(buf);
59  return NULL;
60  }
61  if (feof(f)) {
62  free(buf);
63  return NULL;
64  }
65 
66  size_t buf_len = strlen(buf);
67  if (buf_len > 0) {
68  buf[buf_len - 1] = '\0';
69  }
70 
71  char *newbuf = realloc(buf, buf_len + 1);
72  // realloc behaves like free if buf_len is 0
73  if (!newbuf) {
74  return buf;
75  }
76  return newbuf;
77  }
78  buf = calloc(BS + 1, 1);
79  if (!buf) {
80  return NULL;
81  }
82 
83  len = 0;
84  for (;;) {
85  if (next) {
86  free(buf);
87  buf = next;
88  bufsize = nextlen + blocksize;
89  // len = nextlen;
90  rr = nextlen;
91  rr2 = fread(buf + nextlen, 1, blocksize, f);
92  if (rr2 > 0) {
93  rr += rr2;
94  bufsize += rr2;
95  }
96  next = NULL;
97  nextlen = 0;
98  } else {
99  rr = fread(buf + len, 1, blocksize, f);
100  }
101  if (rr < 1) { // EOF
102  buf[len] = 0;
103  next = NULL;
104  break;
105  }
106  len += rr;
107  // buf[len] = 0;
108  bufsize += blocksize;
109  tmp = realloc(buf, bufsize + 1);
110  if (!tmp) {
111  bufsize -= blocksize;
112  break;
113  }
114  memset(tmp + bufsize - blocksize, 0, blocksize);
115  buf = tmp;
116  }
117  if (sz) {
118  *sz = len;
119  }
120  if (len < 1) {
121  free(buf);
122  return buf = NULL;
123  }
124  buf[len] = 0;
125  return buf;
126 }
127 
128 #if HAVE_HEADER_SYS_MMAN_H
129 static void synchronize(RZ_UNUSED int sig) {
130  // TODO: must be in sdb_sync() or wat?
131  sdb_sync(s);
132  Sdb *n = sdb_new(s->path, s->name, s->lock);
133  if (n) {
134  sdb_config(n, options);
135  sdb_free(s);
136  s = n;
137  }
138 }
139 #endif
140 
141 static int sdb_grep_dump(const char *dbname, int fmt, bool grep,
142  const char *expgrep) {
143  char *v, k[SDB_CDB_MAX_KEY] = { 0 };
144  // local db beacuse is readonly and we dont need to finalize in case of ^C
145  Sdb *db = sdb_new(NULL, dbname, 0);
146  if (!db) {
147  return 1;
148  }
149  sdb_config(db, options);
150  sdb_dump_begin(db);
151  while (sdb_dump_dupnext(db, k, &v, NULL)) {
152  if (grep && !strstr(k, expgrep) && !strstr(v, expgrep)) {
153  free(v);
154  continue;
155  }
156  switch (fmt) {
157  case MODE_ZERO:
158  printf("%s=%s", k, v);
159  break;
160  default:
161  printf("%s=%s\n", k, v);
162  break;
163  }
164  free(v);
165  }
166  switch (fmt) {
167  case MODE_ZERO:
168  fflush(stdout);
169  write_null();
170  break;
171  }
172  sdb_free(db);
173  return 0;
174 }
175 
176 static int sdb_grep(const char *db, int fmt, const char *grep) {
177  return sdb_grep_dump(db, fmt, true, grep);
178 }
179 
180 static int sdb_dump(const char *db, int fmt) {
181  return sdb_grep_dump(db, fmt, false, NULL);
182 }
183 
184 static int insertkeys(Sdb *s, const char **args, int nargs, int mode) {
185  int must_save = 0;
186  if (args && nargs > 0) {
187  int i;
188  for (i = 0; i < nargs; i++) {
189  switch (mode) {
190  case '-':
191  must_save |= sdb_query(s, args[i]);
192  break;
193  case '=':
194  if (strchr(args[i], '=')) {
195  char *v, *kv = (char *)strdup(args[i]);
196  v = strchr(kv, '=');
197  if (v) {
198  *v++ = 0;
199  sdb_disk_insert(s, kv, v);
200  }
201  free(kv);
202  }
203  break;
204  }
205  }
206  }
207  return must_save;
208 }
209 
210 static int createdb(const char *f, const char **args, int nargs) {
211  s = sdb_new(NULL, f, 0);
212  if (!s) {
213  eprintf("Cannot create database\n");
214  return 1;
215  }
216  sdb_config(s, options);
217  int ret = 0;
218  if (args) {
219  int i;
220  for (i = 0; i < nargs; i++) {
221  if (!sdb_text_load(s, args[i])) {
222  eprintf("Failed to load text sdb from %s\n", args[i]);
223  }
224  }
225  } else {
226  size_t len;
227  char *in = slurp(stdin, &len);
228  if (!in) {
229  return 0;
230  }
231  if (!sdb_text_load_buf(s, in, len)) {
232  eprintf("Failed to read text sdb from stdin\n");
233  }
234  free(in);
235  }
236  sdb_sync(s);
237  return ret;
238 }
239 
240 static int showusage(int o) {
241  printf("usage: sdb [-0cdehjJv|-D A B] [-|db] "
242  "[.file]|[-=]|==||[-+][(idx)key[=value] ..]\n");
243  if (o == 2) {
244  printf(" -0 terminate results with \\x00\n"
245  " -c count the number of keys database\n"
246  " -d decode base64 from stdin\n"
247  " -D diff two databases\n"
248  " -e encode stdin as base64\n"
249  " -h show this help\n"
250  " -J enable journaling\n"
251  " -v show version information\n");
252  return 0;
253  }
254  return o;
255 }
256 
257 static int showversion(void) {
258  fflush(stdout);
259  return 0;
260 }
261 
262 static int base64encode(void) {
263  char *out;
264  size_t len = 0;
265  ut8 *in = (ut8 *)slurp(stdin, &len);
266  if (!in) {
267  return 0;
268  }
269  out = sdb_encode(in, (int)len);
270  if (!out) {
271  free(in);
272  return 1;
273  }
274  puts(out);
275  free(out);
276  free(in);
277  return 0;
278 }
279 
280 static int base64decode(void) {
281  ut8 *out;
282  size_t len, ret = 1;
283  char *in = slurp(stdin, &len);
284  if (in) {
285  int declen;
286  out = sdb_decode(in, &declen);
287  if (out && declen >= 0) {
288  write_(1, out, declen);
289  ret = 0;
290  }
291  free(out);
292  free(in);
293  }
294  return ret;
295 }
296 
297 static void dbdiff_cb(const SdbDiff *diff, void *user) {
298  char sbuf[512];
299  int r = sdb_diff_format(sbuf, sizeof(sbuf), diff);
300  if (r < 0) {
301  return;
302  }
303  char *buf = sbuf;
304  char *hbuf = NULL;
305  if ((size_t)r >= sizeof(sbuf)) {
306  hbuf = malloc(r + 1);
307  if (!hbuf) {
308  return;
309  }
310  r = sdb_diff_format(hbuf, r + 1, diff);
311  if (r < 0) {
312  goto beach;
313  }
314  }
315  printf("\x1b[%sm%s\x1b[0m\n", diff->add ? "32" : "31", buf);
316 beach:
317  free(hbuf);
318 }
319 
320 static bool dbdiff(const char *a, const char *b) {
321  Sdb *A = sdb_new(NULL, a, 0);
322  Sdb *B = sdb_new(NULL, b, 0);
323  bool equal = sdb_diff(A, B, dbdiff_cb, NULL);
324  sdb_free(A);
325  sdb_free(B);
326  return equal;
327 }
328 
329 int showcount(const char *db) {
330  ut32 d;
331  s = sdb_new(NULL, db, 0);
332  if (sdb_stats(s, &d, NULL)) {
333  printf("%d\n", d);
334  }
335  // TODO: show version, timestamp information
336  sdb_free(s);
337  return 0;
338 }
339 
340 int main(int argc, const char **argv) {
341  char *line;
342  const char *arg, *grep = NULL;
343  int i, fmt = MODE_DFLT;
344  int db0 = 1, argi = 1;
345  bool interactive = false;
346 
347  /* terminate flags */
348  if (argc < 2) {
349  return showusage(1);
350  }
351  arg = argv[1];
352 
353  if (arg[0] == '-') { // && arg[1] && arg[2]==0) {
354  switch (arg[1]) {
355  case 0:
356  /* no-op */
357  break;
358  case '0':
359  fmt = MODE_ZERO;
360  db0++;
361  argi++;
362  if (db0 >= argc) {
363  return showusage(1);
364  }
365  break;
366  case 'g':
367  db0 += 2;
368  if (db0 >= argc) {
369  return showusage(1);
370  }
371  grep = argv[2];
372  argi += 2;
373  break;
374  case 'J':
376  db0++;
377  argi++;
378  if (db0 >= argc) {
379  return showusage(1);
380  }
381  break;
382  case 'c': return (argc < 3) ? showusage(1) : showcount(argv[2]);
383  case 'v': return showversion();
384  case 'h': return showusage(2);
385  case 'e': return base64encode();
386  case 'd': return base64decode();
387  case 'D':
388  if (argc == 4) {
389  return dbdiff(argv[2], argv[3]) ? 0 : 1;
390  }
391  return showusage(0);
392  default:
393  eprintf("Invalid flag %s\n", arg);
394  break;
395  }
396  }
397 
398  /* sdb - */
399  if (argi == 1 && !strcmp(argv[argi], "-")) {
400  /* no database */
401  argv[argi] = "";
402  if (argc == db0 + 1) {
403  interactive = true;
404  /* if no argument passed */
405  argv[argi] = "-";
406  argc++;
407  argi++;
408  }
409  }
410  /* sdb dbname */
411  if (argc - 1 == db0) {
412  if (grep) {
413  return sdb_grep(argv[db0], fmt, grep);
414  }
415  return sdb_dump(argv[db0], fmt);
416  }
417 #if HAVE_HEADER_SYS_MMAN_H
418  signal(SIGINT, terminate);
419  signal(SIGHUP, synchronize);
420 #endif
421  int ret = 0;
422  if (interactive || !strcmp(argv[db0 + 1], "-")) {
423  if ((s = sdb_new(NULL, argv[db0], 0))) {
424  sdb_config(s, options);
425  int kvs = db0 + 2;
426  if (kvs < argc) {
427  save |= insertkeys(s, argv + argi + 2, argc - kvs, '-');
428  }
429  for (; (line = slurp(stdin, NULL));) {
430  save |= sdb_query(s, line);
431  if (fmt) {
432  fflush(stdout);
433  write_null();
434  }
435  free(line);
436  }
437  }
438  } else if (!strcmp(argv[db0 + 1], "=")) {
439  ret = createdb(argv[db0], NULL, 0);
440  } else if (!strcmp(argv[db0 + 1], "==")) {
441  ret = createdb(argv[db0], argv + db0 + 2, argc - (db0 + 2));
442  } else {
443  s = sdb_new(NULL, argv[db0], 0);
444  if (!s) {
445  return 1;
446  }
447  sdb_config(s, options);
448  for (i = db0 + 1; i < argc; i++) {
449  save |= sdb_query(s, argv[i]);
450  if (fmt) {
451  fflush(stdout);
452  write_null();
453  }
454  }
455  }
456  terminate(ret);
457  return ret;
458 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
#define A(x)
Definition: arc.h:165
#define B(x)
Definition: arc.h:166
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
static int buf_len
Definition: asm_arc.c:22
RZ_API ut8 * sdb_decode(const char *in, int *len)
Definition: base64.c:37
RZ_API char * sdb_encode(const ut8 *bin, int len)
Definition: base64.c:18
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static int buf_size
Definition: debug_qnx.c:35
uint32_t ut32
RZ_API bool sdb_disk_insert(Sdb *s, const char *key, const char *val)
Definition: disk.c:67
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
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
static void dbdiff_cb(const SdbDiff *diff, void *user)
Definition: main.c:297
static int createdb(const char *f, const char **args, int nargs)
Definition: main.c:210
static int insertkeys(Sdb *s, const char **args, int nargs, int mode)
Definition: main.c:184
int main(int argc, const char **argv)
Definition: main.c:340
static int sdb_dump(const char *db, int fmt)
Definition: main.c:180
static bool dbdiff(const char *a, const char *b)
Definition: main.c:320
#define MODE_ZERO
Definition: main.c:11
#define BS
Definition: main.c:35
static void write_null(void)
Definition: main.c:31
static void terminate(RZ_UNUSED int sig)
Definition: main.c:18
static int sdb_grep(const char *db, int fmt, const char *grep)
Definition: main.c:176
int showcount(const char *db)
Definition: main.c:329
static int sdb_grep_dump(const char *dbname, int fmt, bool grep, const char *expgrep)
Definition: main.c:141
static char * slurp(FILE *f, size_t *sz)
Definition: main.c:37
static int base64encode(void)
Definition: main.c:262
static int save
Definition: main.c:14
static int base64decode(void)
Definition: main.c:280
static ut32 options
Definition: main.c:16
static int showusage(int o)
Definition: main.c:240
static Sdb * s
Definition: main.c:15
static int showversion(void)
Definition: main.c:257
#define MODE_DFLT
Definition: main.c:12
RZ_API int sdb_query(Sdb *s, const char *cmd)
Definition: query.c:785
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
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
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 static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment signal
Definition: sflib.h:79
int n
Definition: mipsasm.c:19
string FILE
Definition: benchmark.py:21
line
Definition: setup.py:34
#define eprintf(x, y...)
Definition: rlcc.c:7
#define RZ_UNUSED
Definition: rz_types.h:73
RZ_API bool sdb_dump_dupnext(Sdb *s, char *key, char **value, int *_vlen)
Definition: sdb.c:877
RZ_API Sdb * sdb_new(const char *path, const char *name, int lock)
Definition: sdb.c:47
RZ_API bool sdb_free(Sdb *s)
Definition: sdb.c:206
RZ_API bool sdb_stats(Sdb *s, ut32 *disk, ut32 *mem)
Definition: sdb.c:856
RZ_API void sdb_dump_begin(Sdb *s)
Definition: sdb.c:835
RZ_API bool sdb_sync(Sdb *s)
Definition: sdb.c:803
RZ_API void sdb_config(Sdb *s, int options)
Definition: sdb.c:1041
#define SDB_OPTION_FS
Definition: sdb.h:57
#define SDB_OPTION_JOURNAL
Definition: sdb.h:58
RZ_API bool sdb_text_load(Sdb *s, const char *file)
Definition: text.c:405
RZ_API bool sdb_text_load_buf(Sdb *s, char *buf, size_t sz)
Definition: text.c:386
#define SDB_CDB_MAX_KEY
Definition: sdb.h:21
#define SDB_OPTION_NOSTAMP
Definition: sdb.h:56
#define write_(fd, buf, count)
Definition: sdb_private.h:18
#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
bool add
Definition: sdb.h:139
Definition: sdb.h:63
char * path
Definition: sdb.h:65
int lock
Definition: sdb.h:69
char * name
Definition: sdb.h:66
struct Arg * args
Definition: mipsasm.c:18
RZ_API bool sdb_diff(Sdb *a, Sdb *b, SdbDiffCallback cb, void *cb_user)
Definition: diff.c:159
RZ_API int sdb_diff_format(char *str, int size, const SdbDiff *diff)
Definition: diff.c:6
static int blocksize
Definition: visual.c:15
#define SIGHUP
Definition: win.h:86