Rizin
unix-like reverse engineering framework and cli tools
text.c File Reference
#include "sdb.h"
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include "sdb_private.h"

Go to the source code of this file.

Classes

struct  LoadCtx
 

Macros

#define FLUSH
 
#define ESCAPE_LOOP(fd, str, escapes)
 
#define ESCAPE(c, repl, replsz)
 

Enumerations

enum  LoadState { STATE_NEWLINE , STATE_PATH , STATE_KEY , STATE_VALUE }
 

Functions

static int cmp_ns (const void *a, const void *b)
 
static void write_path (int fd, SdbList *path)
 
static void write_key (int fd, const char *k)
 
static void write_value (int fd, const char *v)
 
static bool save_kv_cb (void *user, const char *k, const char *v)
 
static bool text_save (Sdb *s, int fd, bool sort, SdbList *path)
 
RZ_API bool sdb_text_save_fd (Sdb *s, int fd, bool sort)
 
RZ_API bool sdb_text_save (Sdb *s, const char *file, bool sort)
 
static void load_process_line (LoadCtx *ctx)
 
static char unescape_raw_char (char c)
 
static void load_process_single_char (LoadCtx *ctx)
 
static bool load_process_final_line (LoadCtx *ctx)
 
static void load_ctx_fini (LoadCtx *ctx)
 
static bool load_ctx_init (LoadCtx *ctx, Sdb *s, char *buf, size_t sz)
 
RZ_API bool sdb_text_load_buf (Sdb *s, char *buf, size_t sz)
 
RZ_API bool sdb_text_load (Sdb *s, const char *file)
 

Macro Definition Documentation

◆ ESCAPE

#define ESCAPE (   c,
  repl,
  replsz 
)
Value:
case c: \
FLUSH; \
p++; \
write_(fd, "\\" repl, replsz + 1); \
break;
#define c(i)
Definition: sha256.c:43
static const z80_opcode fd[]
Definition: z80_tab.h:997

Definition at line 91 of file text.c.

◆ ESCAPE_LOOP

#define ESCAPE_LOOP (   fd,
  str,
  escapes 
)
Value:
do { \
const char *p = str; \
const char *n = p; \
while (*n) { \
switch (*n) { escapes } \
n++; \
} \
FLUSH; \
} while (0)
void * p
Definition: libc.cpp:67
int n
Definition: mipsasm.c:19

Definition at line 81 of file text.c.

◆ FLUSH

#define FLUSH
Value:
do { \
if (p != n) { \
write_(fd, p, n - p); \
p = n; \
} \
} while (0)

Definition at line 73 of file text.c.

Enumeration Type Documentation

◆ LoadState

enum LoadState
Enumerator
STATE_NEWLINE 
STATE_PATH 
STATE_KEY 
STATE_VALUE 

Definition at line 209 of file text.c.

209  {
211  STATE_PATH,
212  STATE_KEY,
214 } LoadState;
LoadState
Definition: text.c:209
@ STATE_KEY
Definition: text.c:212
@ STATE_NEWLINE
Definition: text.c:210
@ STATE_PATH
Definition: text.c:211
@ STATE_VALUE
Definition: text.c:213

Function Documentation

◆ cmp_ns()

static int cmp_ns ( const void *  a,
const void *  b 
)
static

Plaintext SDB Format


Files are UTF-8 and use '
' line endings. Always.

Lines starting with '/' denote the path of the namespace for the following data:

/some/namespace

The default path is root, just a slash also means root. These paths are always absolute from the root. Characters that must be escaped in a path are: '/', '\', '
', '\r':

/s\/ome/name\nspa\ce

SDB entries are written each as a single k=v line:

somekey=somevalue

To distinguish these from path lines, if there is a leading '/' in the key, it must be escaped (slashes later in the line don't have to be escaped):

\/slashedkey=somevalue

Other than that, at any postion, '\', '
' and '\r' must be escaped:

some\key=some\nvalue

In the key, '=' must also be escaped (not necessary in the value):

some=key=some=value


Example:

/ key=intheroot \/slashedkey=somevalue some\key=some\nvalue some=key=some=value

/subns some=stuff in the sub-namespace

/subns/deeper this=is in /subns/deeper

Definition at line 64 of file text.c.

64  {
65  const SdbNs *nsa = a;
66  const SdbNs *cia = b;
67  return strcmp(nsa->name, cia->name);
68 }
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: sdb.h:88
char * name
Definition: sdb.h:89

References a, b, and sdb_ns_t::name.

Referenced by text_save().

◆ load_ctx_fini()

static void load_ctx_fini ( LoadCtx ctx)
static

Definition at line 362 of file text.c.

362  {
363  ls_free(ctx->path);
364 }
RZ_API void ls_free(SdbList *list)
Definition: ls.c:191

References ls_free().

Referenced by load_ctx_init(), and sdb_text_load_buf().

◆ load_ctx_init()

static bool load_ctx_init ( LoadCtx ctx,
Sdb s,
char *  buf,
size_t  sz 
)
static

Definition at line 366 of file text.c.

366  {
367  ctx->eof = false;
368  ctx->buf = buf;
369  ctx->bufsz = sz;
370  ctx->root_db = s;
371  ctx->cur_db = s;
372  ctx->pos = 0;
373  ctx->line_begin = 0;
374  ctx->token_begin = 0;
375  ctx->shift = 0;
376  ctx->path = ls_new();
377  ctx->state = STATE_NEWLINE;
378  ctx->unescape = false;
379  if (!ctx->buf || !ctx->path) {
381  return false;
382  }
383  return true;
384 }
voidpf void * buf
Definition: ioapi.h:138
RZ_API SdbList * ls_new(void)
Definition: ls.c:16
static RzSocket * s
Definition: rtr.c:28
static void load_ctx_fini(LoadCtx *ctx)
Definition: text.c:362

References load_ctx_fini(), ls_new(), s, and STATE_NEWLINE.

Referenced by sdb_text_load_buf().

◆ load_process_final_line()

static bool load_process_final_line ( LoadCtx ctx)
static

Definition at line 336 of file text.c.

336  {
337  // load_process_line needs ctx.buf[ctx.pos] to be allocated!
338  // so we need room for one additional byte after the buffer.
339  size_t linesz = ctx->bufsz - ctx->line_begin;
340  char *linebuf = malloc(linesz + 1);
341  if (!linebuf) {
342  return false;
343  }
344  memcpy(linebuf, ctx->buf + ctx->line_begin, linesz);
345  ctx->buf = linebuf;
346  // shift everything by the size we skipped
347  ctx->bufsz -= ctx->line_begin;
348  ctx->pos = linesz;
349  ctx->token_begin -= ctx->line_begin;
350  SdbListIter *it;
351  void *token_off_tmp;
352  ls_foreach (ctx->path, it, token_off_tmp) {
353  it->data = (void *)((size_t)token_off_tmp - ctx->line_begin);
354  }
355  ctx->line_begin = 0;
357  free(linebuf);
358  ctx->buf = NULL;
359  return true;
360 }
#define NULL
Definition: cris-opc.c:27
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
#define ls_foreach(list, it, pos)
Definition: ls.h:31
Definition: ls.h:17
void * data
Definition: ls.h:18
static void load_process_line(LoadCtx *ctx)
Definition: text.c:234

References ls_iter_t::data, free(), load_process_line(), ls_foreach, malloc(), memcpy(), and NULL.

Referenced by sdb_text_load_buf().

◆ load_process_line()

static void load_process_line ( LoadCtx ctx)
static

Definition at line 234 of file text.c.

234  {
235  ctx->unescape = false;
236  // finish up the line
237  ctx->buf[ctx->pos - ctx->shift] = '\0';
238  switch (ctx->state) {
239  case STATE_PATH: {
240  ls_push(ctx->path, (void *)ctx->token_begin);
241  SdbListIter *it;
242  void *token_off_tmp;
243  ctx->cur_db = ctx->root_db;
244  ls_foreach (ctx->path, it, token_off_tmp) {
245  size_t token_off = (size_t)token_off_tmp;
246  if (!ctx->buf[token_off]) {
247  continue;
248  }
249  ctx->cur_db = sdb_ns(ctx->cur_db, ctx->buf + token_off, 1);
250  if (!ctx->cur_db) {
251  ctx->cur_db = ctx->root_db;
252  break;
253  }
254  }
255  ls_destroy(ctx->path);
256  break;
257  }
258  case STATE_VALUE: {
259  const char *k = ctx->buf + ctx->line_begin;
260  const char *v = ctx->buf + ctx->token_begin;
261  if (!*k || !*v) {
262  break;
263  }
264  sdb_set(ctx->cur_db, k, v, 0);
265  break;
266  }
267  default:
268  break;
269  }
270  // prepare for next line
271  ctx->shift = 0;
272  ctx->state = STATE_NEWLINE;
273 }
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API void ls_destroy(SdbList *list)
Definition: ls.c:176
#define ls_push(x, y)
Definition: ls.h:75
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
int size_t
Definition: sftypes.h:40

References k, ls_destroy(), ls_foreach, ls_push, sdb_ns(), sdb_set(), STATE_NEWLINE, STATE_PATH, STATE_VALUE, and v.

Referenced by load_process_final_line(), and load_process_single_char().

◆ load_process_single_char()

static void load_process_single_char ( LoadCtx ctx)
static

Definition at line 288 of file text.c.

288  {
289  char c = ctx->buf[ctx->pos];
290  if (c == '\n' || c == '\r') {
292  ctx->pos++;
293  return;
294  }
295 
296  if (ctx->state == STATE_NEWLINE) {
297  ctx->line_begin = ctx->pos;
298  // at the start of a line, decide whether it's a path or a k=v
299  // by whether there is a leading slash.
300  if (c == '/') {
301  ctx->state = STATE_PATH;
302  ctx->token_begin = ctx->pos + 1;
303  ctx->pos++;
304  c = ctx->buf[ctx->pos];
305  return;
306  }
307  ctx->state = STATE_KEY;
308  }
309 
310  if (ctx->unescape) {
311  ctx->buf[ctx->pos - ctx->shift] = unescape_raw_char(c);
312  ctx->unescape = false;
313  } else if (c == '\\') {
314  // got a backslash, the next char, unescape in the next iteration or die!
315  ctx->shift++;
316  ctx->unescape = true;
317  } else if (ctx->state == STATE_PATH && c == '/') {
318  // new path token
319  ctx->buf[ctx->pos - ctx->shift] = '\0';
320  ls_push(ctx->path, (void *)ctx->token_begin);
321  ctx->token_begin = ctx->pos + 1;
322  ctx->shift = 0;
323  } else if (ctx->state == STATE_KEY && c == '=') {
324  // switch from key to value mode
325  ctx->buf[ctx->pos - ctx->shift] = '\0';
326  ctx->token_begin = ctx->pos + 1;
327  ctx->shift = 0;
328  ctx->state = STATE_VALUE;
329  } else if (ctx->shift) {
330  // just some char, shift it back if necessary
331  ctx->buf[ctx->pos - ctx->shift] = c;
332  }
333  ctx->pos++;
334 }
static char unescape_raw_char(char c)
Definition: text.c:275

References c, load_process_line(), ls_push, STATE_KEY, STATE_NEWLINE, STATE_PATH, STATE_VALUE, and unescape_raw_char().

Referenced by sdb_text_load_buf().

◆ save_kv_cb()

static bool save_kv_cb ( void *  user,
const char *  k,
const char *  v 
)
static

Definition at line 139 of file text.c.

139  {
140  int fd = *(int *)user;
141  write_key(fd, k);
142  write_(fd, "=", 1);
143  write_value(fd, v);
144  write_(fd, "\n", 1);
145  return true;
146 }
#define write_(fd, buf, count)
Definition: sdb_private.h:18
static void write_key(int fd, const char *k)
Definition: text.c:117
static void write_value(int fd, const char *v)
Definition: text.c:129

References fd, k, v, write_, write_key(), and write_value().

Referenced by text_save().

◆ sdb_text_load()

RZ_API bool sdb_text_load ( Sdb s,
const char *  file 
)

Definition at line 405 of file text.c.

405  {
406  int fd = open(file, O_RDONLY | O_BINARY);
407  if (fd < 0) {
408  return false;
409  }
410  bool r = false;
411  struct stat st;
412  if (fstat(fd, &st) || !st.st_size) {
413  goto beach;
414  }
415 #if HAVE_HEADER_SYS_MMAN_H
416  char *x = mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
417  if (x == MAP_FAILED) {
418  goto beach;
419  }
420 #else
421  char *x = calloc(1, st.st_size);
422  if (!x) {
423  goto beach;
424  }
425  if (read(fd, x, st.st_size) != st.st_size) {
426  free(x);
427  goto beach;
428  }
429 #endif
430  r = sdb_text_load_buf(s, x, st.st_size);
431 #if HAVE_HEADER_SYS_MMAN_H
432  munmap(x, st.st_size);
433 #else
434  free(x);
435 #endif
436 beach:
437  close(fd);
438  return r;
439 }
#define O_BINARY
Definition: cpipe.c:13
#define r
Definition: crypto_rc6.c:12
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 static offset fstat
Definition: sflib.h:107
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 char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags mmap
Definition: sflib.h:115
static const void static count static fd struct stat static buf struct pollfd unsigned static timeout void static offset munmap
Definition: sflib.h:43
int x
Definition: mipsasm.c:20
#define PROT_READ
Definition: sftypes.h:95
#define PROT_WRITE
Definition: sftypes.h:96
#define MAP_PRIVATE
Definition: sftypes.h:102
#define O_RDONLY
Definition: sftypes.h:486
Definition: gzappend.c:170
Definition: sftypes.h:80
RZ_API bool sdb_text_load_buf(Sdb *s, char *buf, size_t sz)
Definition: text.c:386
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

References calloc(), close, fd, free(), fstat, MAP_PRIVATE, mmap, munmap, O_BINARY, O_RDONLY, PROT_READ, PROT_WRITE, r, read(), s, sdb_text_load_buf(), and x.

Referenced by createdb(), and rz_project_load_file_raw().

◆ sdb_text_load_buf()

RZ_API bool sdb_text_load_buf ( Sdb s,
char *  buf,
size_t  sz 
)

Definition at line 386 of file text.c.

386  {
387  if (!sz) {
388  return true;
389  }
390  LoadCtx ctx;
391  if (!load_ctx_init(&ctx, s, buf, sz)) {
392  return false;
393  }
394  bool ret = true;
395  while (ctx.pos < ctx.bufsz) {
397  }
398  if (ctx.line_begin < ctx.bufsz && ctx.state != STATE_NEWLINE) {
400  }
401  load_ctx_fini(&ctx);
402  return ret;
403 }
Definition: text.c:216
static bool load_ctx_init(LoadCtx *ctx, Sdb *s, char *buf, size_t sz)
Definition: text.c:366
static void load_process_single_char(LoadCtx *ctx)
Definition: text.c:288
static bool load_process_final_line(LoadCtx *ctx)
Definition: text.c:336

References load_ctx_fini(), load_ctx_init(), load_process_final_line(), load_process_single_char(), s, and STATE_NEWLINE.

Referenced by createdb(), and sdb_text_load().

◆ sdb_text_save()

RZ_API bool sdb_text_save ( Sdb s,
const char *  file,
bool  sort 
)

Definition at line 199 of file text.c.

199  {
200  int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
201  if (fd < 0) {
202  return false;
203  }
204  bool r = sdb_text_save_fd(s, fd, sort);
205  close(fd);
206  return r;
207 }
#define O_WRONLY
Definition: sftypes.h:487
#define O_CREAT
Definition: sftypes.h:489
#define O_TRUNC
Definition: sftypes.h:492
RZ_API bool sdb_text_save_fd(Sdb *s, int fd, bool sort)
Definition: text.c:189

References close, fd, O_BINARY, O_CREAT, O_TRUNC, O_WRONLY, r, s, and sdb_text_save_fd().

Referenced by rz_project_save_file().

◆ sdb_text_save_fd()

RZ_API bool sdb_text_save_fd ( Sdb s,
int  fd,
bool  sort 
)

Definition at line 189 of file text.c.

189  {
190  SdbList *path = ls_new();
191  if (!path) {
192  return false;
193  }
194  bool r = text_save(s, fd, sort, path);
195  ls_free(path);
196  return r;
197 }
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
Definition: ls.h:22
static bool text_save(Sdb *s, int fd, bool sort, SdbList *path)
Definition: text.c:148

References fd, ls_free(), ls_new(), path, r, s, and text_save().

Referenced by sdb_text_save().

◆ text_save()

static bool text_save ( Sdb s,
int  fd,
bool  sort,
SdbList path 
)
static

Definition at line 148 of file text.c.

148  {
149  // path
150  write_path(fd, path);
151  write_(fd, "\n", 1);
152 
153  // k=v entries
154  if (sort) {
155  SdbList *l = sdb_foreach_list(s, true);
156  SdbKv *kv;
157  SdbListIter *it;
158  ls_foreach (l, it, kv) {
159  save_kv_cb(&fd, sdbkv_key(kv), sdbkv_value(kv));
160  }
161  ls_free(l);
162  } else {
163  // This is faster when sorting is not needed.
165  }
166 
167  // sub-namespaces
168  SdbList *l = s->ns;
169  if (sort) {
170  l = ls_clone(l);
171  ls_sort(l, cmp_ns);
172  }
173  SdbNs *ns;
174  SdbListIter *it;
175  ls_foreach (l, it, ns) {
176  write_(fd, "\n", 1);
177  ls_push(path, ns->name);
178  text_save(ns->sdb, fd, sort, path);
179  ls_pop(path);
180  }
181  if (l != s->ns) {
182  ls_free(l);
183  }
184 
185  return true;
186 }
RZ_API void * ls_pop(SdbList *list)
Definition: ls.c:244
RZ_API SdbList * ls_clone(SdbList *list)
Definition: ls.c:265
RZ_API bool ls_sort(SdbList *list, SdbListComparator cmp)
Definition: ls.c:119
RZ_API bool sdb_foreach(Sdb *s, SdbForeachCallback cb, void *user)
Definition: sdb.c:758
RZ_API SdbList * sdb_foreach_list(Sdb *s, bool sorted)
Definition: sdb.c:630
static char * sdbkv_key(const SdbKv *kv)
Definition: sdbht.h:21
static char * sdbkv_value(const SdbKv *kv)
Definition: sdbht.h:25
Definition: sdbht.h:14
Sdb * sdb
Definition: sdb.h:91
static int cmp_ns(const void *a, const void *b)
Definition: text.c:64
static void write_path(int fd, SdbList *path)
Definition: text.c:98
static bool save_kv_cb(void *user, const char *k, const char *v)
Definition: text.c:139

References cmp_ns(), fd, ls_clone(), ls_foreach, ls_free(), ls_pop(), ls_push, ls_sort(), sdb_ns_t::name, path, s, save_kv_cb(), sdb_ns_t::sdb, sdb_foreach(), sdb_foreach_list(), sdbkv_key(), sdbkv_value(), write_, and write_path().

Referenced by sdb_text_save_fd().

◆ unescape_raw_char()

static char unescape_raw_char ( char  c)
inlinestatic

Definition at line 275 of file text.c.

275  {
276  switch (c) {
277  case 'n':
278  return '\n';
279  case 'r':
280  return '\r';
281  case 't':
282  return '\t';
283  default:
284  return c;
285  }
286 }

References c.

Referenced by load_process_single_char().

◆ write_key()

static void write_key ( int  fd,
const char *  k 
)
static

Definition at line 117 of file text.c.

117  {
118  // escape leading '/'
119  if (*k == '/') {
120  write_(fd, "\\", 1);
121  }
122  ESCAPE_LOOP(fd, k,
123  ESCAPE('\\', "\\", 1);
124  ESCAPE('=', "=", 1);
125  ESCAPE('\n', "n", 1);
126  ESCAPE('\r', "r", 1););
127 }
#define ESCAPE(c, repl, replsz)
Definition: text.c:91
#define ESCAPE_LOOP(fd, str, escapes)
Definition: text.c:81

References ESCAPE, ESCAPE_LOOP, fd, k, and write_.

Referenced by save_kv_cb().

◆ write_path()

static void write_path ( int  fd,
SdbList path 
)
static

Definition at line 98 of file text.c.

98  {
99  write_(fd, "/", 1); // always print a /, even if path is empty
100  SdbListIter *it;
101  const char *path_token;
102  bool first = true;
103  ls_foreach (path, it, path_token) {
104  if (first) {
105  first = false;
106  } else {
107  write_(fd, "/", 1);
108  }
109  ESCAPE_LOOP(fd, path_token,
110  ESCAPE('\\', "\\", 1);
111  ESCAPE('/', "/", 1);
112  ESCAPE('\n', "n", 1);
113  ESCAPE('\r', "r", 1););
114  }
115 }

References ESCAPE, ESCAPE_LOOP, fd, ls_foreach, path, and write_.

Referenced by text_save().

◆ write_value()

static void write_value ( int  fd,
const char *  v 
)
static

Definition at line 129 of file text.c.

129  {
130  ESCAPE_LOOP(fd, v,
131  ESCAPE('\\', "\\", 1);
132  ESCAPE('\n', "n", 1);
133  ESCAPE('\r', "r", 1););
134 }

References ESCAPE, ESCAPE_LOOP, fd, and v.

Referenced by save_kv_cb().