void erl_luam_maybe_atom(lua_drv_t *driver_data, char *buf, int index) { long i; int is_atom; char *atom; ei_decode_long(buf, &index, &i); lua_getglobal(driver_data->L, "erlang"); lua_getfield(driver_data->L, -1, "t_atom"); lua_getmetatable(driver_data->L, -3); is_atom = lua_rawequal(driver_data->L, -1, -2); lua_pop(driver_data->L, 3); if (is_atom) { atom = (char*)lua_touserdata(driver_data->L, i); ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_ATOM, ATOM_OK, ERL_DRV_ATOM, driver_mk_atom(atom), ERL_DRV_TUPLE, 2, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); } else { ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_ATOM, driver_mk_atom("false"), ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); } }
void erl_luam_multipcall(lua_drv_t *driver_data, char *buf, int index) { long args, level, ret_results; ei_decode_long(buf, &index, &args); /* level := function's index - 1 */ level = lua_gettop(driver_data->L) - args - 1; if(lua_pcall(driver_data->L, args, LUA_MULTRET, 0) == 0) { ret_results = lua_gettop(driver_data->L) - level; ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_INT, (ErlDrvTermData) ret_results, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport,spec,sizeof(spec)/sizeof(spec[0])); } else { const char *err = lua_tostring(driver_data->L, -1); ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_THROW, ERL_DRV_ATOM, driver_mk_atom("lua_error"), ERL_DRV_STRING, (ErlDrvTermData) err, strlen(err), ERL_DRV_TUPLE, 2, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport,spec,sizeof(spec)/sizeof(spec[0])); } }
void testcase_printf(TestCaseState_t *tcs, char *frmt, ...) { InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; ErlDrvTermData msg[12]; va_list va; va_start(va, frmt); #if HAVE_VSNPRINTF vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); #else vsprintf(itcs->comment_buf, frmt, va); #endif va_end(va); msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) driver_mk_atom("print"); msg[2] = ERL_DRV_PORT; msg[3] = itcs->port_id; msg[4] = ERL_DRV_ATOM; msg[5] = driver_mk_atom(itcs->visible.testcase_name); msg[6] = ERL_DRV_STRING; msg[7] = (ErlDrvTermData) itcs->comment_buf; msg[8] = (ErlDrvTermData) strlen(itcs->comment_buf); msg[9] = ERL_DRV_TUPLE; msg[10] = (ErlDrvTermData) 4; erl_drv_output_term(itcs->port_id, msg, 11); }
static void reply_boolean(lua_drv_t *driver_data, int res) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_ATOM, driver_mk_atom(res ? "true" : "false"), ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); }
static void reply_throw(lua_drv_t *driver_data, const char *err) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_THROW, ERL_DRV_STRING, (ErlDrvTermData) err, strlen(err), ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); }
static void return_ok(bdb_drv_t* pdrv) { ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok")}; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(pdrv->port, spec, sizeof(spec) / sizeof(spec[0])); #else ErlDrvTermData mkport = driver_mk_port(pdrv->port); erl_drv_output_term(mkport, spec, sizeof(spec) / sizeof(spec[0])); #endif }
void erl_lua_gettop(lua_drv_t *driver_data, char *buf, int index) { int size; size = lua_gettop(driver_data->L); ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_INT, (ErlDrvTermData) size, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); }
static void process_unkown(bdb_drv_t *bdb_drv, ErlIOVec *ev) { // Return {error, unkown_command} ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), ERL_DRV_ATOM, driver_mk_atom("uknown_command"), ERL_DRV_TUPLE, 2}; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); #else ErlDrvTermData mkport = driver_mk_port(bdb_drv->port); erl_drv_output_term(mkport, spec, sizeof(spec) / sizeof(spec[0])); #endif }
static void fail_term(ErlDrvTermData* msg, int len, int line) { int status = erl_drv_output_term(driver_mk_port(erlang_port), msg, len); if (status == 1) { char buf[1024]; sprintf(buf, "%s:%d: unexpected success", __FILE__, line); driver_failure_atom(erlang_port, buf); } else if (status == 0) { char buf[1024]; sprintf(buf, "%s:%d: unexpected port error", __FILE__, line); driver_failure_atom(erlang_port, buf); } }
static void return_error_tuple(bdb_drv_t* pdrv, char* err_msg) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, driver_mk_atom("error"), ERL_DRV_ATOM, driver_mk_atom(err_msg), ERL_DRV_TUPLE, 2}; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(pdrv->port, spec, sizeof(spec) / sizeof(spec[0])); #else ErlDrvTermData mkport = driver_mk_port(pdrv->port); erl_drv_output_term(mkport, spec, sizeof(spec) / sizeof(spec[0])); #endif }
void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { int res; ErlDrvPort port = (ErlDrvPort) drv_data; ErlDrvTermData msg[] = { ERL_DRV_PORT, driver_mk_port(port), ERL_DRV_ATOM, driver_mk_atom("caller"), ERL_DRV_PID, driver_caller(port), ERL_DRV_TUPLE, (ErlDrvTermData) 3 }; res = erl_drv_output_term(driver_mk_port(port), msg, sizeof(msg)/sizeof(ErlDrvTermData)); if (res <= 0) driver_failure_atom(port, "erl_drv_output_term failed"); }
void erl_lua_next(lua_drv_t *driver_data, char *buf, int index) { long i; int ret; ei_decode_long(buf, &index, &i); ret = lua_next(driver_data->L, i); ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_INT, (ErlDrvTermData) ret, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); }
void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; ErlDrvTermData result_atom; ErlDrvTermData msg[12]; itcs->visible.command = buf; itcs->visible.command_len = len; if (setjmp(itcs->done_jmp_buf) == 0) { testcase_run((TestCaseState_t *) itcs); itcs->result = TESTCASE_SUCCEEDED; } switch (itcs->result) { case TESTCASE_SUCCEEDED: result_atom = driver_mk_atom("succeeded"); break; case TESTCASE_SKIPPED: result_atom = driver_mk_atom("skipped"); break; case TESTCASE_FAILED: default: result_atom = driver_mk_atom("failed"); break; } msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) result_atom; msg[2] = ERL_DRV_PORT; msg[3] = itcs->port_id; msg[4] = ERL_DRV_ATOM; msg[5] = driver_mk_atom(itcs->visible.testcase_name); msg[6] = ERL_DRV_STRING; msg[7] = (ErlDrvTermData) itcs->comment; msg[8] = (ErlDrvTermData) strlen(itcs->comment); msg[9] = ERL_DRV_TUPLE; msg[10] = (ErlDrvTermData) 4; erl_drv_output_term(itcs->port_id, msg, 11); }
static int send_wrapped(ErlDrvTermData port, ErlDrvTermData* term, int n) { ErlDrvTermData *wrapped = (ErlDrvTermData *) driver_alloc (sizeof(ErlDrvTermData) * (n + 6)); wrapped[0] = ERL_DRV_ATOM; wrapped[1] = driver_mk_atom ("pwd"); wrapped[2] = ERL_DRV_PORT; wrapped[3] = port; memcpy(wrapped + 4, term, n * sizeof(ErlDrvTermData)); wrapped[n+4] = ERL_DRV_TUPLE; wrapped[n+5] = 3; int result = erl_drv_output_term (port, wrapped, n + 6); driver_free(wrapped); return result; }
void erl_lua_tolstring(lua_drv_t *driver_data, char *buf, int index) { size_t len; long i; const char *str; ei_decode_long(buf, &index, &i); str = lua_tolstring(driver_data->L, i, &len); ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_BUF2BINARY, (ErlDrvTermData) str, len, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); }
static void return_ok_empty_list(bdb_drv_t* pdrv) { ErlDrvTermData empty_spec[] = { ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_NIL, ERL_DRV_LIST, 1, ERL_DRV_TUPLE, 2}; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(pdrv->port, empty_spec, sizeof(empty_spec) / sizeof(empty_spec[0])); #else ErlDrvTermData mkport = driver_mk_port(pdrv->port); erl_drv_output_term(mkport, empty_spec, sizeof(empty_spec) / sizeof(empty_spec[0])); #endif }
void erl_lua_objlen(lua_drv_t *driver_data, char *buf, int index) { long i; size_t size; ei_decode_long(buf, &index, &i); #if LUA_VERSION_NUM > 501 size = lua_rawlen(driver_data->L, i); #else size = lua_objlen(driver_data->L, i); #endif ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_INT, (ErlDrvTermData) size, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); }
void erl_lua_tonumber(lua_drv_t *driver_data, char *buf, int index) { long i; double res; int encode_i = 0; int size; char *eibuf; ei_decode_long(buf, &index, &i); res = lua_tonumber(driver_data->L, i); ei_encode_version(NULL, &encode_i); if ((long long) res == res) { ei_encode_longlong(NULL, &encode_i, (long long) res); size = encode_i; encode_i = 0; eibuf = malloc(sizeof(char) * (size + 1)); ei_encode_version(eibuf, &encode_i); ei_encode_longlong(eibuf, &encode_i, res); } else { ei_encode_double(NULL, &encode_i, res); size = encode_i; encode_i = 0; eibuf = malloc(sizeof(char) * (size + 1)); ei_encode_version(eibuf, &encode_i); ei_encode_double(eibuf, &encode_i, res); } ErlDrvTermData spec[] = { ERL_DRV_ATOM, ATOM_OK, ERL_DRV_BUF2BINARY, (ErlDrvTermData) eibuf, size, ERL_DRV_TUPLE, 2 }; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); free(eibuf); }
static void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { consume_timeslice_data_t *ctsd = (consume_timeslice_data_t *) drv_data; int res; if (ctsd->consume_timeslice) { int res = erl_drv_consume_timeslice(ctsd->port, 50); if (res < 0) { driver_failure_atom(ctsd->port, "erl_drv_consume_timeslice() failed"); return; } } res = erl_drv_output_term(ctsd->tport, ctsd->cmd_msg, sizeof(ctsd->cmd_msg)/sizeof(ErlDrvTermData)); if (res <= 0) { driver_failure_atom(ctsd->port, "erl_drv_output_term() failed"); return; } }
static ErlDrvSSizeT syslogdrv_control(ErlDrvData handle, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { syslogdrv_t* d = (syslogdrv_t*)handle; int index = 0, version, arity, type, size; if (command != SYSLOGDRV_OPEN) { return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } if (ei_decode_version(buf, &index, &version)) { return encode_error(*rbuf, "badver"); } if (ei_decode_tuple_header(buf, &index, &arity) || arity != 4) { return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } if (ei_get_type(buf, &index, &type, &size)) { return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } if (type == ERL_STRING_EXT) { long logopt, facility, len; ErlDrvBinary* ref = 0; syslogdrv_t* nd = (syslogdrv_t*)driver_alloc(sizeof(syslogdrv_t)); if (nd == NULL) { return encode_error(*rbuf, "enomem"); } nd->ident = driver_alloc(size+1); if (nd->ident == NULL) { return encode_error(*rbuf, "enomem"); } if (ei_decode_string(buf, &index, nd->ident)) { driver_free(nd->ident); driver_free(nd); return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } if (ei_decode_long(buf, &index, &logopt) || ei_decode_long(buf, &index, &facility)) { driver_free(nd->ident); driver_free(nd); return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } if (ei_get_type(buf, &index, &type, &size)) { driver_free(nd->ident); driver_free(nd); return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } if (type != ERL_BINARY_EXT) { driver_free(nd->ident); driver_free(nd); return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } ref = driver_alloc_binary(size); if (ref == NULL) { return encode_error(*rbuf, "enomem"); } if (ei_decode_binary(buf, &index, ref->orig_bytes, &len)) { driver_free_binary(ref); driver_free(nd->ident); driver_free(nd); return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } nd->logopt = (int)logopt; nd->facility = (int)facility; nd->open = 1; { ErlDrvTermData refdata = TERM_DATA(ref->orig_bytes); ErlDrvPort port = d->port; ErlDrvTermData pid = driver_caller(port); ErlDrvData data = (ErlDrvData)nd; nd->port = driver_create_port(port, pid, DRV_NAME, data); if (nd->port == (ErlDrvPort)-1) { driver_free_binary(ref); driver_free(nd->ident); driver_free(nd); return (ErlDrvSSizeT)ERL_DRV_ERROR_GENERAL; } set_port_control_flags(nd->port, PORT_CONTROL_FLAG_BINARY); ErlDrvTermData term[] = { ERL_DRV_EXT2TERM, refdata, ref->orig_size, ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_PORT, driver_mk_port(nd->port), ERL_DRV_TUPLE, 2, ERL_DRV_TUPLE, 2, }; erl_drv_output_term(driver_mk_port(port), term, sizeof term/sizeof *term); } driver_free_binary(ref); return 0; } else { return (ErlDrvSSizeT)ERL_DRV_ERROR_BADARG; } }
static void process_count( bdb_drv_t* pdrv, ErlIOVec *ev) { DB_BTREE_STAT* btree_stats; DB_HASH_STAT* hash_stats; int ret, count; count = 0; if (pdrv->pcfg == NULL) { return_error_tuple(pdrv, "Database not opened!"); return; } if (pdrv->pcfg->pdb == NULL) { return_error_tuple(pdrv, "Database not opened!"); return; } while (1) { if (pdrv->pcfg->db_type == DB_BTREE) { ret = pdrv->pcfg->pdb->stat(pdrv->pcfg->pdb, NULL, &btree_stats, DB_FAST_STAT); if (ret != 0) { if (count > 2) { return_error_tuple(pdrv, db_strerror(ret)); break; } else { count = count + 1; usleep(1000); } } else { ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_INT, btree_stats->bt_nkeys, ERL_DRV_TUPLE, 2}; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(pdrv->port, spec, sizeof(spec) / sizeof(spec[0])); #else ErlDrvTermData mkport = driver_mk_port(pdrv->port); erl_drv_output_term(mkport, spec, sizeof(spec) / sizeof(spec[0])); #endif free(btree_stats); break; } } else { ret = pdrv->pcfg->pdb->stat(pdrv->pcfg->pdb, NULL, &hash_stats, 0); if (ret != 0) { if (count > 2) { return_error_tuple(pdrv, db_strerror(ret)); break; } else { count = count + 1; usleep(1000); } } else { ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_INT, hash_stats->hash_nkeys, ERL_DRV_TUPLE, 2}; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(pdrv->port, spec, sizeof(spec) / sizeof(spec[0])); #else ErlDrvTermData mkport = driver_mk_port(pdrv->port); erl_drv_output_term(mkport, spec, sizeof(spec) / sizeof(spec[0])); #endif free(hash_stats); break; } } } return; }
static void bulk_get_hash (u_int32_t offset, u_int32_t count, bdb_drv_t *pdrv) { int ret; size_t retklen, retdlen; void *retkey, *retdata; void* p; DB* pdb; DBC* pdbc = NULL; DBT key, data; db_recno_t curr = 1; db_recno_t limit = 1; db_recno_t actual_count = 0; ErlDrvTermData *spec; u_int32_t spec_items, idx; curr = offset; limit = offset + count; pdb = pdrv->pcfg->pdb; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); data.data = pdrv->pcfg->buffer; data.ulen = pdrv->pcfg->bulk_get_buffer_size_bytes; data.flags = DB_DBT_USERMEM; if ((ret = pdb->cursor(pdb, NULL, &pdbc, 0)) != 0) { return_error_tuple(pdrv, db_strerror(ret)); return; } //Fast forward to the correct index idx = 1; while ((ret = pdbc->c_get(pdbc, &key, &data, DB_NEXT)) == 0) { idx++; if (idx >= offset) { break; } } if ((ret != DB_NOTFOUND) && (ret != 0)) { return_error_tuple(pdrv, db_strerror(ret)); } else if (ret == DB_NOTFOUND) { return_ok_empty_list(pdrv); } else { if ((ret = pdbc->c_get(pdbc, &key, &data, DB_MULTIPLE_KEY | DB_CURRENT)) != 0) { if (ret == DB_NOTFOUND) { return_ok_empty_list(pdrv); } else { return_error_tuple(pdrv, db_strerror(ret)); } } else { //First count the number of recs... for (DB_MULTIPLE_INIT(p, &data); curr < limit; curr++) { DB_MULTIPLE_KEY_NEXT(p, &data, retkey, retklen, retdata, retdlen); if (p == NULL) { break; } else { actual_count++; } } spec_items = (8 * actual_count) + 7; spec = malloc(sizeof(ErlDrvTermData) * spec_items); if (spec == NULL) { return_error_tuple(pdrv, "Could not allocate memory for operation!"); } else { spec[0] = ERL_DRV_ATOM; spec[1] = driver_mk_atom("ok"); //Now pipe the data... p = NULL; curr = 0; for (DB_MULTIPLE_INIT(p, &data); curr < actual_count; curr++) { DB_MULTIPLE_KEY_NEXT(p, &data, retkey, retklen, retdata, retdlen); if (p == NULL) { break; } else { idx = 2 + (curr * 8); spec[idx + 0] = ERL_DRV_STRING; spec[idx + 1] = (ErlDrvTermData)retkey; spec[idx + 2] = retklen; spec[idx + 3] = ERL_DRV_STRING; spec[idx + 4] = (ErlDrvTermData)retdata; spec[idx + 5] = retdlen; spec[idx + 6] = ERL_DRV_TUPLE; spec[idx + 7] = 2; } } spec[spec_items - 5] = ERL_DRV_NIL; spec[spec_items - 4] = ERL_DRV_LIST; spec[spec_items - 3] = actual_count + 1; spec[spec_items - 2] = ERL_DRV_TUPLE; spec[spec_items - 1] = 2; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(pdrv->port, spec, spec_items); #else ErlDrvTermData mkport = driver_mk_port(pdrv->port); erl_drv_output_term(mkport, spec, spec_items); #endif free(spec); } } } pdbc->c_close(pdbc); return; }
static void get (u_int32_t key_size, void* praw_key, bdb_drv_t *pdrv) { DB* pdb = pdrv->pcfg->pdb; DBT key; DBT data; int ret, count; memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); key.data = praw_key, key.size = key_size, data.flags = DB_DBT_MALLOC; count = 0; while (1) { ret = pdb->get(pdb, 0, &key, &data, 0); if (ret == 0) { ErlDrvTermData spec[] = { ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_STRING, (ErlDrvTermData) data.data, data.size, ERL_DRV_TUPLE, 2}; #if ((ERL_DRV_EXTENDED_MAJOR_VERSION == 1) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION == 0))) driver_output_term(pdrv->port, spec, sizeof(spec) / sizeof(spec[0])); #else ErlDrvTermData mkport = driver_mk_port(pdrv->port); erl_drv_output_term(mkport, spec, sizeof(spec) / sizeof(spec[0])); #endif free(data.data); break; } else if (ret == DB_LOCK_DEADLOCK) { if (count < 5) { count = count + 1; usleep(1000); } else { return_error_tuple(pdrv, db_strerror(ret)); break; } } else { if (ret != DB_NOTFOUND) { return_error_tuple(pdrv, db_strerror(ret)); } else { return_error_tuple(pdrv, "not_found"); } break; } } return; }
static void output_term(ErlDrvTermData* msg, int len) { if (erl_drv_output_term(driver_mk_port(erlang_port), msg, len) <= 0) { driver_failure_atom(erlang_port, "erl_drv_output_term_failed"); } }
static void send_term_drv_run(ErlDrvData port, char *buf, ErlDrvSizeT count) { char buf7[1024]; ErlDrvTermData spec[1024]; ErlDrvTermData* msg = spec; ErlDrvBinary* bins[15]; int bin_ix = 0; ErlDrvSInt64 s64[15]; int s64_ix = 0; ErlDrvUInt64 u64[15]; int u64_ix = 0; int i = 0; for (i=0; i<count; i++) switch (buf[i]) { case 0: msg[0] = ERL_DRV_NIL; msg += 1; break; case 1: /* Most term types inside a tuple. */ { double f = 3.1416; msg[0] = ERL_DRV_ATOM; msg[1] = driver_mk_atom("blurf"); msg[2] = ERL_DRV_INT; msg[3] = (ErlDrvTermData) 42; msg[4] = ERL_DRV_NIL; msg[5] = ERL_DRV_INT; msg[6] = (ErlDrvTermData) -42; msg[7] = ERL_DRV_TUPLE; msg[8] = (ErlDrvTermData) 0; msg[9] = ERL_DRV_PORT; msg[10] = driver_mk_port(erlang_port); msg[11] = ERL_DRV_STRING_CONS; msg[12] = (ErlDrvTermData) "abc"; msg[13] = (ErlDrvTermData) 3; msg[14] = ERL_DRV_LIST; msg[15] = (ErlDrvTermData) 3; msg[16] = ERL_DRV_STRING; msg[17] = (ErlDrvTermData) "kalle"; msg[18] = (ErlDrvTermData) 5; msg[19] = ERL_DRV_FLOAT; msg[20] = (ErlDrvTermData) &f; msg[21] = ERL_DRV_PID; msg[22] = driver_connected(erlang_port); msg[23] = ERL_DRV_MAP; msg[24] = (ErlDrvTermData) 0; msg[25] = ERL_DRV_TUPLE; msg[26] = (ErlDrvTermData) 8; msg += 27; } break; case 2: /* Deep stack */ { int i; for (i = 0; i < 400; i += 2) { msg[i] = ERL_DRV_INT; msg[i+1] = (ErlDrvTermData) (i / 2); } msg[i] = ERL_DRV_NIL; msg[i+1] = ERL_DRV_LIST; msg[i+2] = (ErlDrvTermData) 201; msg += i+3; } break; case 3: /* Binaries */ { ErlDrvBinary* bin; int i; bin = bins[bin_ix++] = driver_alloc_binary(256); for (i = 0; i < 256; i++) { bin->orig_bytes[i] = i; } msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) bin; msg[2] = (ErlDrvTermData) 256; msg[3] = (ErlDrvTermData) 0; msg[4] = ERL_DRV_BINARY; msg[5] = (ErlDrvTermData) bin; msg[6] = (ErlDrvTermData) 256-23-17; msg[7] = (ErlDrvTermData) 23; msg[8] = ERL_DRV_TUPLE; msg[9] = (ErlDrvTermData) 2; msg += 10; } break; case 4: /* Pids */ msg[0] = ERL_DRV_PID; msg[1] = driver_connected(erlang_port); msg[2] = ERL_DRV_PID; msg[3] = driver_caller(erlang_port); msg[4] = ERL_DRV_TUPLE; msg[5] = (ErlDrvTermData) 2; msg += 6; break; case 5: msg += make_ext_term_list(msg, 0); break; case 6: msg[0] = ERL_DRV_INT; msg[1] = ~((ErlDrvTermData) 0); msg[2] = ERL_DRV_UINT; msg[3] = ~((ErlDrvTermData) 0); msg[4] = ERL_DRV_TUPLE; msg[5] = (ErlDrvTermData) 2; msg += 6; break; case 7: { int len = 0; memset(buf7, 17, sizeof(buf7)); /* empty heap binary */ msg[len++] = ERL_DRV_BUF2BINARY; msg[len++] = (ErlDrvTermData) NULL; /* NULL is ok if size == 0 */ msg[len++] = (ErlDrvTermData) 0; /* empty heap binary again */ msg[len++] = ERL_DRV_BUF2BINARY; msg[len++] = (ErlDrvTermData) buf7; /* ptr is ok if size == 0 */ msg[len++] = (ErlDrvTermData) 0; /* heap binary */ msg[len++] = ERL_DRV_BUF2BINARY; msg[len++] = (ErlDrvTermData) buf7; msg[len++] = (ErlDrvTermData) 17; /* off heap binary */ msg[len++] = ERL_DRV_BUF2BINARY; msg[len++] = (ErlDrvTermData) buf7; msg[len++] = (ErlDrvTermData) sizeof(buf7); msg[len++] = ERL_DRV_TUPLE; msg[len++] = (ErlDrvTermData) 4; msg += len; break; } case 8: msg[0] = ERL_DRV_NIL; msg += 1; break; case 9: msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) driver_mk_atom(""); msg += 2; break; case 10: msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) driver_mk_atom("an_atom"); msg += 2; break; case 11: msg[0] = ERL_DRV_INT; msg[1] = (ErlDrvTermData) -4711; msg += 2; break; case 12: msg[0] = ERL_DRV_UINT; msg[1] = (ErlDrvTermData) 4711; msg += 2; break; case 13: msg[0] = ERL_DRV_PORT; msg[1] = driver_mk_port(erlang_port); msg += 2; break; case 14: { ErlDrvBinary *dbin = bins[bin_ix++] = driver_alloc_binary(0); msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) dbin; msg[2] = (ErlDrvTermData) 0; msg[3] = (ErlDrvTermData) 0; msg += 4; break; } case 15: { static const char buf[] = "hejsan"; ErlDrvBinary *dbin = bins[bin_ix++] = driver_alloc_binary(sizeof(buf)-1); if (dbin) memcpy((void *) dbin->orig_bytes, (void *) buf, sizeof(buf)-1); msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) dbin; msg[2] = (ErlDrvTermData) (dbin ? sizeof(buf)-1 : 0); msg[3] = (ErlDrvTermData) 0; msg += 4; break; } case 16: msg[0] = ERL_DRV_BUF2BINARY; msg[1] = (ErlDrvTermData) NULL; msg[2] = (ErlDrvTermData) 0; msg += 3; break; case 17: { static const char buf[] = ""; msg[0] = ERL_DRV_BUF2BINARY; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; msg += 3; break; } case 18: { static const char buf[] = "hoppsan"; msg[0] = ERL_DRV_BUF2BINARY; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; msg += 3; break; } case 19: msg[0] = ERL_DRV_STRING; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) 0; msg += 3; break; case 20: { static const char buf[] = ""; msg[0] = ERL_DRV_STRING; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; msg += 3; break; } case 21: { static const char buf[] = "hippsan"; msg[0] = ERL_DRV_STRING; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; msg += 3; break; } case 22: msg[0] = ERL_DRV_TUPLE; msg[1] = (ErlDrvTermData) 0; msg += 2; break; case 23: msg[0] = ERL_DRV_NIL; msg[1] = ERL_DRV_LIST; msg[2] = (ErlDrvTermData) 1; msg += 3; break; case 24: msg[0] = ERL_DRV_PID; msg[1] = driver_connected(erlang_port); msg += 2; break; case 25: msg[0] = ERL_DRV_NIL; msg[1] = ERL_DRV_STRING_CONS; msg[2] = (ErlDrvTermData) ""; msg[3] = (ErlDrvTermData) 0; msg += 4; break; case 26: { static double my_float = 0.0; msg[0] = ERL_DRV_FLOAT; msg[1] = (ErlDrvTermData) &my_float; msg += 2; break; } case 27: { static char buf[] = {131, 106}; /* [] */ msg[0] = ERL_DRV_EXT2TERM; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf); msg += 3; break; } case 28: { ErlDrvUInt64* x = &u64[u64_ix++]; *x = ~((ErlDrvUInt64) 0); msg[0] = ERL_DRV_UINT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 29: { ErlDrvUInt64* x = &u64[u64_ix++]; *x = ((ErlDrvUInt64) 4711) << 32; msg[0] = ERL_DRV_UINT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 30: { ErlDrvUInt64* x = &u64[u64_ix++]; *x = 4711; msg[0] = ERL_DRV_UINT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 31: { ErlDrvUInt64* x = &u64[u64_ix++]; *x = 0; msg[0] = ERL_DRV_UINT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 32: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = ((((ErlDrvUInt64) 0x7fffffff) << 32) | ((ErlDrvUInt64) 0xffffffff)); msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 33: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = (ErlDrvSInt64) (((ErlDrvUInt64) 4711) << 32); msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 34: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = 4711; msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 35: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = 0; msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 36: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = -1; msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 37: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = -4711; msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 38: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = ((ErlDrvSInt64) ((ErlDrvUInt64) 4711) << 32)*-1; msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 39: { ErlDrvSInt64* x = &s64[s64_ix++]; *x = ((ErlDrvSInt64) 1) << 63; msg[0] = ERL_DRV_INT64; msg[1] = (ErlDrvTermData) x; msg += 2; break; } case 40: { msg[0] = ERL_DRV_MAP; msg[1] = (ErlDrvTermData) 0; msg += 2; break; } case 41: /* Most term types inside a map */ case 42: { double f = 3.1416; if (buf[i] == 41) { *msg++ = ERL_DRV_ATOM; *msg++ = driver_mk_atom("blurf"); } *msg++ = ERL_DRV_INT; *msg++ = (ErlDrvTermData)42; *msg++ = ERL_DRV_NIL; *msg++ = ERL_DRV_INT; *msg++ = (ErlDrvTermData)-42; *msg++ = ERL_DRV_TUPLE; *msg++ = (ErlDrvTermData)0; *msg++ = ERL_DRV_PORT; *msg++ = driver_mk_port(erlang_port); *msg++ = ERL_DRV_STRING_CONS; *msg++ = (ErlDrvTermData)"abc"; *msg++ = (ErlDrvTermData)3; *msg++ = ERL_DRV_LIST; *msg++ = (ErlDrvTermData)3; *msg++ = ERL_DRV_STRING; *msg++ = (ErlDrvTermData)"kalle"; *msg++ = (ErlDrvTermData)5; *msg++ = ERL_DRV_FLOAT; *msg++ = (ErlDrvTermData)&f; *msg++ = ERL_DRV_PID; *msg++ = driver_connected(erlang_port); *msg++ = ERL_DRV_MAP; *msg++ = (ErlDrvTermData)0; if (buf[i] == 42) { *msg++ = ERL_DRV_ATOM; *msg++ = driver_mk_atom("blurf"); } *msg++ = ERL_DRV_MAP; *msg++ = (ErlDrvTermData)4; break; } case 127: /* Error cases */ { long refc; ErlDrvBinary* bin = bins[bin_ix++] = driver_alloc_binary(256); FAIL_TERM(msg, 0); msg[0] = ERL_DRV_LIST; msg[1] = (ErlDrvTermData) 0; FAIL_TERM(msg, 2); /* Not an atom */ msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) driver_connected(erlang_port); FAIL_TERM(msg, 2); msg[0] = ERL_DRV_ATOM; msg[1] = driver_term_nil; FAIL_TERM(msg, 2); /* Not a pid */ msg[0] = ERL_DRV_PID; msg[1] = (ErlDrvTermData) driver_mk_atom("blurf"); FAIL_TERM(msg, 2); msg[0] = ERL_DRV_PID; msg[1] = driver_term_nil; FAIL_TERM(msg, 2); /* Not a port */ msg[0] = ERL_DRV_PORT; msg[1] = (ErlDrvTermData) driver_mk_atom("blurf"); FAIL_TERM(msg, 2); msg[0] = ERL_DRV_PORT; msg[1] = driver_term_nil; FAIL_TERM(msg, 2); /* Missing parameter on stack */ msg[0] = ERL_DRV_STRING_CONS; msg[1] = (ErlDrvTermData) "abc"; msg[2] = (ErlDrvTermData) 3; FAIL_TERM(msg, 3); /* * The first binary reference is correct, the second is incorrect. * There should not be any "binary leak". */ msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) bin; msg[2] = (ErlDrvTermData) 256; msg[3] = (ErlDrvTermData) 0; msg[4] = ERL_DRV_BINARY; msg[5] = (ErlDrvTermData) bin; msg[6] = (ErlDrvTermData) 257; msg[7] = (ErlDrvTermData) 0; msg[8] = ERL_DRV_TUPLE; msg[9] = (ErlDrvTermData) 2; FAIL_TERM(msg, 10); msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) bin; msg[2] = (ErlDrvTermData) 256; msg[3] = (ErlDrvTermData) 0; msg[4] = ERL_DRV_BINARY; msg[5] = (ErlDrvTermData) bin; msg[6] = (ErlDrvTermData) 256; msg[7] = (ErlDrvTermData) 50; msg[8] = ERL_DRV_TUPLE; msg[9] = (ErlDrvTermData) 2; FAIL_TERM(msg, 10); /* * We have succefully built two binaries. We expect the ref count * to be 1 (SMP) or 3 (non-SMP). */ refc = driver_binary_get_refc(bin); if (refc > 3) { char sbuf[128]; sprintf(sbuf, "bad_refc:%ld", refc); driver_failure_atom(erlang_port, sbuf); } driver_free_binary(bin); FAIL_TERM(msg, make_ext_term_list(msg, 1)); /* * Check that we fail for missing args. * * We setup valid terms but pass a too small size. We * want valid terms since we want to verify that the * failure really is due to the small size. */ msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) driver_mk_atom("an_atom"); FAIL_TERM(msg, 1); msg[0] = ERL_DRV_INT; msg[1] = (ErlDrvTermData) -4711; FAIL_TERM(msg, 1); msg[0] = ERL_DRV_UINT; msg[1] = (ErlDrvTermData) 4711; FAIL_TERM(msg, 1); msg[0] = ERL_DRV_PORT; msg[1] = driver_mk_port(erlang_port); FAIL_TERM(msg, 1); { char buf[] = "hejsan"; ErlDrvBinary *dbin = driver_alloc_binary(sizeof(buf)-1); if (!dbin) driver_failure_posix(erlang_port, ENOMEM); else { memcpy((void *) dbin->orig_bytes, (void *) buf, sizeof(buf)-1); msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) dbin; msg[2] = (ErlDrvTermData) sizeof(buf)-1; msg[3] = (ErlDrvTermData) 0; FAIL_TERM(msg, 1); FAIL_TERM(msg, 2); FAIL_TERM(msg, 3); driver_free_binary(dbin); } } { char buf[] = "hoppsan"; msg[0] = ERL_DRV_BUF2BINARY; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; FAIL_TERM(msg, 1); FAIL_TERM(msg, 2); } { char buf[] = "hippsan"; msg[0] = ERL_DRV_STRING; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; FAIL_TERM(msg, 1); FAIL_TERM(msg, 2); } msg[0] = ERL_DRV_TUPLE; msg[1] = (ErlDrvTermData) 0; FAIL_TERM(msg, 1); msg[0] = ERL_DRV_NIL; msg[1] = ERL_DRV_LIST; msg[2] = (ErlDrvTermData) 1; FAIL_TERM(msg, 2); msg[0] = ERL_DRV_PID; msg[1] = driver_connected(erlang_port); FAIL_TERM(msg, 1); msg[0] = ERL_DRV_NIL; msg[1] = ERL_DRV_STRING_CONS; msg[2] = (ErlDrvTermData) ""; msg[3] = (ErlDrvTermData) 0; FAIL_TERM(msg, 2); FAIL_TERM(msg, 3); { double my_float = 0.0; msg[0] = ERL_DRV_FLOAT; msg[1] = (ErlDrvTermData) &my_float; FAIL_TERM(msg, 1); } { char buf[] = {131, 106}; /* [] */ msg[0] = ERL_DRV_EXT2TERM; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf); FAIL_TERM(msg, 1); FAIL_TERM(msg, 2); } msg[0] = ERL_DRV_MAP; msg[1] = (ErlDrvTermData) 0; FAIL_TERM(msg, 1); /* map with duplicate key */ msg[0] = ERL_DRV_ATOM; msg[1] = driver_mk_atom("key"); msg[2] = ERL_DRV_NIL; msg[3] = ERL_DRV_ATOM; msg[4] = driver_mk_atom("key"); msg[5] = ERL_DRV_INT; msg[6] = (ErlDrvTermData) -4711; msg[7] = ERL_DRV_MAP; msg[8] = 2; FAIL_TERM(msg, 9); /* Signal end of test case */ msg[0] = ERL_DRV_NIL; erl_drv_output_term(driver_mk_port(erlang_port), msg, 1); return; } break; default: driver_failure_atom(erlang_port, "bad_request"); break; } if (count > 1) { *msg++ = ERL_DRV_NIL; *msg++ = ERL_DRV_LIST; *msg++ = count + 1; } output_term(spec, msg-spec); if ((bin_ix|s64_ix|u64_ix) > 15) abort(); while (bin_ix) { driver_free_binary(bins[--bin_ix]); } }
static void reply_ok(lua_drv_t *driver_data) { ErlDrvTermData spec[] = {ERL_DRV_ATOM, ATOM_OK}; erl_drv_output_term(driver_data->drvport, spec, sizeof(spec) / sizeof(spec[0])); }
static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { EchoDrvData* data_p = (EchoDrvData *) drv_data; ErlDrvPort port = data_p->erlang_port; switch (buf[0]) { case ECHO_DRV_OUTPUT: { driver_output(port, buf+1, len-1); break; } case ECHO_DRV_OUTPUT2: { driver_output2(port, "a", 1, buf+1, len-1); break; } case ECHO_DRV_OUTPUT_BINARY: { ErlDrvBinary *bin = driver_alloc_binary(len-1); memcpy(&bin->orig_bytes, buf+1, len-1); driver_output_binary(port, "a", 1, bin, 1, len - 2); driver_free_binary(bin); break; } case ECHO_DRV_OUTPUTV: { ErlIOVec iov; ErlDrvSizeT sz; driver_enq(port, buf + 1, len - 1); sz = driver_peekqv(port, &iov); driver_outputv(port, "a", 1, &iov, 0); driver_deq(port, sz); break; } case ECHO_DRV_SET_TIMER: { driver_set_timer(port, 10); break; } case ECHO_DRV_FAILURE_EOF: { driver_failure_eof(port); break; } case ECHO_DRV_FAILURE_ATOM: { driver_failure_atom(port, buf+1); break; } case ECHO_DRV_FAILURE_POSIX: { driver_failure_posix(port, EAGAIN); break; } case ECHO_DRV_FAILURE: { driver_failure(port, buf[1]); break; } case ECHO_DRV_OUTPUT_TERM: case ECHO_DRV_DRIVER_OUTPUT_TERM: case ECHO_DRV_SEND_TERM: case ECHO_DRV_DRIVER_SEND_TERM: { ErlDrvTermData term[] = { ERL_DRV_ATOM, driver_mk_atom("echo"), ERL_DRV_PORT, driver_mk_port(port), ERL_DRV_BUF2BINARY, (ErlDrvTermData)(buf+1), (ErlDrvTermData)(len - 1), ERL_DRV_TUPLE, 3}; switch (buf[0]) { case ECHO_DRV_OUTPUT_TERM: erl_drv_output_term(driver_mk_port(port), term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_DRIVER_OUTPUT_TERM: driver_output_term(port, term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_SEND_TERM: driver_send_term(port, data_p->caller, term, sizeof(term) / sizeof(ErlDrvTermData)); break; case ECHO_DRV_DRIVER_SEND_TERM: erl_drv_send_term(driver_mk_port(port), data_p->caller, term, sizeof(term) / sizeof(ErlDrvTermData)); break; } break; } case ECHO_DRV_SAVE_CALLER: data_p->caller = driver_caller(port); break; default: break; } }