int cli_event_define(cli_events_t *ctx, unsigned id, const char *name, enum ev_type type, enum multiple_handling multiple) { struct cli_event *ev = &ctx->events[id]; if (id >= ctx->max) { cli_event_error_str(ctx, "cli_event_define: event id out of range"); return -1; } if (multiple == multiple_sum && (type != ev_int && type != ev_time && type != ev_data_fast)) { cli_event_error_str(ctx, "cli_event_define: can only sum ev_int, ev_time, and ev_data_fast"); return -1; } if (type == ev_data_fast && multiple != multiple_sum) { cli_event_error_str(ctx, "cli_event_define: ev_data_fast can only be sumed"); return -1; } if (multiple == multiple_concat && type != ev_data) { cli_event_error_str(ctx, "cli_event_define: only ev_data can be concatenated"); return -1; } /* default was ev_none */ ev->type = type; ev->name = name; ev->type = type; ev->multiple = multiple; if (type == ev_data_fast) ev->u.v_int = CRC_INIT_VAL; return 0; }
void cli_event_int(cli_events_t *ctx, unsigned id, uint64_t arg) { struct cli_event *ev = get_event(ctx, id); if (!ev) return; if (ev->type != ev_int) { cli_event_error_str(ctx, "cli_event_int must be called with ev_int type"); return; } switch (ev->multiple) { case multiple_last: ev->u.v_int = arg; ev->count++; break; case multiple_sum: ev->count++; ev->u.v_int += arg; break; case multiple_chain: { union ev_val val; val.v_int = arg; ev_chain(ctx, ev, &val); break; } } }
static inline struct cli_event *get_event(cli_events_t *ctx, unsigned id) { if (!ctx) return NULL; if (id >= ctx->max) { cli_event_error_str(ctx, "event id out of range"); return NULL; } return &ctx->events[id]; }
void cli_event_string(cli_events_t *ctx, unsigned id, const char *str) { struct cli_event *ev = get_event(ctx, id); if (!ev) return; if (ev->type != ev_string) { cli_event_error_str(ctx, "cli_event_string must be called with ev_string type"); return; } event_string(ctx, ev, str); }
/* TODO: field in ctx, id of last bytecode that called magicscandesc, reset * after hooks/other bytecodes are run. TODO: need a more generic solution * to avoid uselessly recursing on bytecode-unpacked files, but also a way to * override the limit if we need it in a special situation */ int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*data, int32_t len) { char err[128]; int32_t res; cli_ctx *cctx = (cli_ctx*)ctx->ctx; if (len < 0) { cli_warnmsg("Bytecode API: called with negative length!\n"); API_MISUSE(); return -1; } if (!ctx->outfd) { ctx->tempfile = cli_gentemp(cctx ? cctx->engine->tmpdir : NULL); if (!ctx->tempfile) { cli_dbgmsg("Bytecode API: Unable to allocate memory for tempfile\n"); cli_event_error_oom(EV, 0); return -1; } ctx->outfd = open(ctx->tempfile, O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600); if (ctx->outfd == -1) { ctx->outfd = 0; cli_warnmsg("Bytecode API: Can't create file %s: %s\n", ctx->tempfile, cli_strerror(errno, err, sizeof(err))); cli_event_error_str(EV, "cli_bcapi_write: Can't create temporary file"); free(ctx->tempfile); return -1; } cli_dbgmsg("bytecode opened new tempfile: %s\n", ctx->tempfile); } cli_event_fastdata(ctx->bc_events, BCEV_WRITE, data, len); if (cli_checklimits("bytecode api", cctx, ctx->written + len, 0, 0)) return -1; res = cli_writen(ctx->outfd, data, len); if (res > 0) ctx->written += res; if (res == -1) { cli_warnmsg("Bytecode API: write failed: %s\n", cli_strerror(errno, err, sizeof(err))); cli_event_error_str(EV, "cli_bcapi_write: write failed"); } return res; }
void cli_event_time_stop(cli_events_t *ctx, unsigned id) { struct timeval tv; struct cli_event *ev = get_event(ctx, id); if (!ev) return; if (ev->type != ev_time) { cli_event_error_str(ctx, "cli_event_time* must be called with ev_time type"); return; } gettimeofday(&tv, NULL); ev->u.v_int += ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; }
void cli_event_fastdata(cli_events_t *ctx, unsigned id, const void *data, uint32_t len) { struct cli_event *ev = get_event(ctx, id); if (!ev) return; if (ev->type != ev_data_fast) { cli_event_error_str(ctx, "cli_event_fastdata must be called with ev_data_fast"); return; } ev->u.v_int = CrcUpdate(ev->u.v_int, data, len); ev->count += len; /* when we are done we should invert all bits, but since we are just * comparing it doesn't matter */ }
void cli_event_time_nested_start(cli_events_t *ctx, unsigned id, unsigned nestedid) { struct timeval tv; struct cli_event *ev = get_event(ctx, id); struct cli_event *evnested = get_event(ctx, nestedid); if (!ev || !evnested) return; if (ev->type != ev_time || evnested->type != ev_time) { cli_event_error_str(ctx, "cli_event_time* must be called with ev_time type"); return; } gettimeofday(&tv, NULL); ev->u.v_int -= ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; ev->u.v_int += evnested->u.v_int; ev->count++; }
void cli_event_data(cli_events_t *ctx, unsigned id, const void *data, uint32_t len) { struct cli_event *ev = get_event(ctx, id); if (!ev) return; if (ev->type != ev_data) { cli_event_error_str(ctx, "cli_event_string must be called with ev_data type"); return; } switch (ev->multiple) { case multiple_last: { void *v_data = cli_realloc2(ev->u.v_data, len); if (v_data) { ev->u.v_data = v_data; memcpy(v_data, data, len); ev->count = len; } else { cli_event_error_oom(ctx, len); } break; } case multiple_concat: { void *v_data = cli_realloc2(ev->u.v_data, ev->count + len); if (v_data) { ev->u.v_data = v_data; memcpy((char*)v_data + ev->count, data, len); ev->count += len; } else { cli_event_error_oom(ctx, ev->count + len); } break; } } }