static void iv_open(t_iconvdrv *iv, char *tocode, char *fromcode) { int len; iconv_t cd; ErlDrvBinary *bin; if ((cd = iconv_open(tocode, fromcode)) == (iconv_t) -1) { driver_send_error(iv, &am_einval); } else { len = sizeof(iconv_t); if (!(bin = driver_alloc_binary(len+1))) { iconv_close(cd); driver_send_error(iv, &am_enomem); } else { memcpy(bin->orig_bytes, &cd, len); if (!strcasecmp(tocode + strlen(tocode) -6, "IGNORE")) { /* GLIBC's iconv is annoying and will throw the failure code for * invalid sequences even though we specify //IGNORE so we have to * keep track if we initalized this conversion handle with //IGNORE * or not so we can disregard the error. */ bin->orig_bytes[len] = 1; } else { bin->orig_bytes[len] = 0; } driver_send_bin(iv, bin, len+1); driver_free_binary(bin); } } return; }
static void free_binary(ErtsIOQBinary *b, int driver) { if (driver) driver_free_binary(&b->driver); else if (erts_refc_dectest(&b->nif.intern.refc, 0) == 0) erts_bin_free(&b->nif); }
static int reply_ok_binary(descriptor_t *desc, char *ptr, int beg_offset, int length) { ErlDrvTermData msg[24]; int i = 0; int res; i = LOAD_PORT(msg, i, driver_mk_port(desc->port)); i = LOAD_ATOM(msg, i, am_ok); i = LOAD_BINARY(msg, i, edtk_alloced_ptr2ErlDrvBinary(ptr), beg_offset, length); i = LOAD_TUPLE(msg, i, 3); edtk_debug("%s: i = %d, ptr = 0x%lx, start = %d, end = %d", __FUNCTION__, i, ptr, beg_offset, length); res = driver_output_term(desc->port, msg, i); /* driver_output_term() incrs refc, and we're done, so decr refc */ /* ** We _know_ that "ptr" points to memory allocated by ** edtk_driver_alloc_wrapper(), so edtk_alloced_ptr2ErlDrvBinary() ** is safe in this case. If it weren't safe, then the binary ** must be returned by an xtra_return, which means we ** reply_ok_binary()) are never called! */ driver_free_binary(edtk_alloced_ptr2ErlDrvBinary(ptr)); edtk_debug("%s: res = %d", __FUNCTION__, res); return res; }
void es_peepEvents2(ErlDrvPort port, ErlDrvTermData caller, char *bp) { SDL_Event events[256]; int numevents, res, i, sz; Uint32 mask; char *start; ErlDrvBinary * bin; ErlDrvTermData rt[8]; mask = * (Uint32 *) bp; bp += sizeof(Uint32); numevents = *bp++; SDL_PumpEvents(); res = SDL_PeepEvents(events, numevents, SDL_GETEVENT, mask); bin = driver_alloc_binary(res*MAX_EVENT_SIZE); bp = start = bin->orig_bytes; for (i = 0; i < res; i++) { bp = encode_event(&(events[i]), bp); } sz = bp-start; rt[0] = ERL_DRV_ATOM; rt[1]=driver_mk_atom((char *) "_esdl_result_"); rt[2] = ERL_DRV_BINARY; rt[3] = (ErlDrvTermData) bin; rt[4] = sz; rt[5] = 0; rt[6] = ERL_DRV_TUPLE; rt[7] = 2; driver_send_term(port,caller,rt,8); driver_free_binary(bin); }
int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller) { ErlDrvBinary* bin; int i; int num_vertices; GLdouble *n; int AP; int a_max = 2; int i_max = 6; num_vertices = * (int *) buff; buff += 8; /* Align */ n = (double *) buff; buff += 8*3; egl_tess.alloc_max = a_max*num_vertices*3; bin = driver_alloc_binary(egl_tess.alloc_max*sizeof(GLdouble)); egl_tess.error = 0; egl_tess.tess_coords = (double *) bin->orig_bytes; memcpy(egl_tess.tess_coords,buff,num_vertices*3*sizeof(GLdouble)); egl_tess.index_max = i_max*3*num_vertices; egl_tess.tess_index_list = (int *) driver_alloc(sizeof(int) * egl_tess.index_max); egl_tess.tess_coords = (double *) bin->orig_bytes; egl_tess.index_n = 0; egl_tess.alloc_n = num_vertices*3; gluTessNormal(tess, n[0], n[1], n[2]); gluTessBeginPolygon(tess, 0); gluTessBeginContour(tess); for (i = 0; i < num_vertices; i++) { gluTessVertex(tess, egl_tess.tess_coords+3*i, egl_tess.tess_coords+3*i); } gluTessEndContour(tess); gluTessEndPolygon(tess); AP = 0; ErlDrvTermData *rt; rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+egl_tess.index_n*2)); rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_"); for(i=0; i < egl_tess.index_n; i++) { rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) egl_tess.tess_index_list[i]; }; rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = egl_tess.index_n+1; rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin; rt[AP++] = egl_tess.alloc_n*sizeof(GLdouble); rt[AP++] = 0; rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin} rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple driver_send_term(port,caller,rt,AP); /* fprintf(stderr, "List %d: %d %d %d \r\n", */ /* res, */ /* n_pos, */ /* (tess_alloc_vertex-new_vertices)*sizeof(GLdouble), */ /* num_vertices*6*sizeof(GLdouble)); */ driver_free_binary(bin); driver_free(egl_tess.tess_index_list); driver_free(rt); return 0; }
wxeCommand::~wxeCommand() { int n = 0; while(bin[n]) { if(bin[n]->bin) driver_free_binary(bin[n]->bin); driver_free(bin[n++]); } driver_free(buffer); }
void edtk_driver_free_wrapper(void *p) { ErlDrvBinary *eb; edtk_debug("%s: top", __FUNCTION__); if ((eb = edtk_alloced_ptr2ErlDrvBinary(p)) != NULL) { edtk_debug("%s: eb = 0x%lx p = 0x%lx", __FUNCTION__, eb, p); driver_free_binary(eb); } }
static int zlib_output_init(ZLibData* d) { if (d->bin != NULL) driver_free_binary(d->bin); if ((d->bin = driver_alloc_binary(d->binsz_need)) == NULL) return -1; d->binsz = d->binsz_need; d->s.next_out = (unsigned char*)d->bin->orig_bytes; d->s.avail_out = d->binsz; return 0; }
static void av_decoder_decoded(ErlDrvData drv_data, ErlDrvThreadData thread_data) { H264Decoder *decoder = (H264Decoder *)drv_data; H264Frame *frame = (H264Frame *)thread_data; // fprintf(stderr, "Decoding finished: %p %ld\r\n", frame->yuv, frame->yuv ? frame->yuv->orig_size : -1); if(frame->yuv) { // av_log(NULL,AV_LOG_WARNING,"\nPORTyuv:: %i\n",decoder->port); ErlDrvTermData reply[] = { ERL_DRV_ATOM, driver_mk_atom("yuv"), ERL_DRV_PORT, driver_mk_port(decoder->port), ERL_DRV_BINARY, (ErlDrvTermData)frame->yuv, (ErlDrvTermData)frame->yuv->orig_size, 0, ERL_DRV_TUPLE, 3 }; driver_output_term(decoder->port, reply, sizeof(reply) / sizeof(reply[0])); driver_free_binary(frame->yuv); } else if(frame->sample){ // av_log(NULL,AV_LOG_WARNING,"\nPORTsample:: %i\n",decoder->port); ErlDrvTermData reply[] = { ERL_DRV_ATOM, driver_mk_atom("sample"), ERL_DRV_PORT, driver_mk_port(decoder->port), ERL_DRV_BINARY, (ErlDrvTermData)frame->sample, (ErlDrvTermData)frame->sample->orig_size, 0, ERL_DRV_TUPLE, 3 }; driver_output_term(decoder->port, reply, sizeof(reply) / sizeof(reply[0])); driver_free_binary(frame->sample); } else { // av_log(decoder->dec,AV_LOG_ERROR,"NOT YUV"); av_log(NULL,AV_LOG_WARNING,"\nPORTelse:: %i\n",decoder->port); ErlDrvTermData reply[] = { ERL_DRV_ATOM, driver_mk_atom("yuv"), ERL_DRV_PORT, driver_mk_port(decoder->port), ERL_DRV_TUPLE, 2 }; driver_output_term(decoder->port, reply, sizeof(reply) / sizeof(reply[0])); } driver_free(frame); }
/* * Send compressed or uncompressed data * and restart output procesing */ static int zlib_output(ZLibData* d) { if (d->bin != NULL) { int len = d->binsz - d->s.avail_out; if (len > 0) { if (driver_output_binary(d->port, NULL, 0, d->bin, 0, len) < 0) return -1; } driver_free_binary(d->bin); d->bin = NULL; d->binsz = 0; } return zlib_output_init(d); }
static void zlib_stop(ErlDrvData e) { ZLibData* d = (ZLibData*)e; if (d->state == ST_DEFLATE) deflateEnd(&d->s); else if (d->state == ST_INFLATE) inflateEnd(&d->s); if (d->bin != NULL) driver_free_binary(d->bin); driver_free(d); }
void wxeCommand::Delete() { int n = 0; if(buffer) { while(bin[n].from) { if(bin[n].bin) driver_free_binary(bin[n].bin); n++; } if(len > 64) driver_free(buffer); buffer = NULL; } op = -2; }
static void ready_async(ErlDrvData handle, ErlDrvThreadData async_data) { spidermonkey_drv_t *dd = (spidermonkey_drv_t *) handle; js_call *call_data = (js_call *) async_data; driver_output_term(dd->port, call_data->return_terms, call_data->return_term_count); driver_free_binary(call_data->args); if (call_data->return_string != NULL) { driver_free((void *) call_data->return_string); } driver_free(call_data); }
static void video_async_decode(void *async_data){ H264Frame *frame = (H264Frame *)async_data; H264Decoder *handle = frame->decoder; AVCodecContext *avctx = handle->dec; AVCodec *codec = avctx->codec; AVPacket avpkt; av_init_packet(&avpkt); struct timeval tv1; struct timeval tv2; gettimeofday(&tv1, NULL); int frame_ready = 0, len,i; AVFrame *decoded; decoded = avcodec_alloc_frame(); frame_ready = sizeof(AVFrame)*2; avpkt.data = (uint8_t *)frame->h264->orig_bytes; avpkt.size = frame->h264->orig_size; len = avcodec_decode_video2(handle->dec, decoded, &frame_ready, &avpkt); // av_log(avctx,AV_LOG_ERROR,"\nORIGSIZE: %i; LEN %i \n",avpkt.size,len); if(len == -1) { av_free(decoded); return; }; if(frame_ready) { int width = handle->dec->width; int height = handle->dec->height; if(handle->scale_ctx==NULL) { fprintf(stderr, "Started stream from camera %dx%d\r\n", width, height); handle->scale_ctx = sws_getContext( width, height, avctx->pix_fmt, width, height, avctx->pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL ); } int stride_size = width*height; frame->yuv = driver_alloc_binary(stride_size*3/2); uint8_t *yuv_data = (uint8_t *)frame->yuv->orig_bytes; uint8_t *plane[4] = {yuv_data, yuv_data+stride_size, yuv_data+stride_size+stride_size/4, NULL}; int stride[4] = {width, width/2, width/2, 0}; sws_scale(handle->scale_ctx, (const uint8_t **)decoded->data, decoded->linesize, 0, height, plane, stride); } gettimeofday(&tv2, NULL); handle->total_time += (tv2.tv_sec * 1000 + tv2.tv_usec / 1000) - (tv1.tv_sec * 1000 + tv1.tv_usec / 1000); av_free(decoded); driver_free_binary(frame->h264); }
static void get_blob(Cmd *cmd) { char *buff = cmd->data; int len = cmd->size; Gd *gd = cmd->gd; int index = 0; void *imgData = NULL; int size = 0; ErlDrvBinary * bin; long quality; ei_decode_version(buff, &index, NULL); ei_decode_long(buff, &index, &quality); if (NULL == gd->image) { driver_failure_atom(gd->port, "null_image"); return; } imgData = gd->blob(gd->image, &size, quality); if (NULL == imgData) { driver_failure_posix(gd->port, ENOMEM); return; } bin = driver_alloc_binary(size); if (NULL == bin) { driver_failure_posix(gd->port, ENOMEM); return; } memcpy(bin->orig_bytes, imgData, size); gdFree(imgData); ErlDrvTermData spec[] = { ERL_DRV_PORT, driver_mk_port(gd->port), ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_BINARY, bin, size, 0, ERL_DRV_TUPLE, 3}; driver_output_term(gd->port, spec, sizeof(spec) / sizeof(ERL_DRV_PORT)); driver_free_binary(bin); }
static void md4drv_from_erlang(ErlDrvData drv_data, char *buf, int len) { MD4_CTX context; unsigned char digest[16]; t_md4drv *md4 = (t_md4drv *) drv_data; ErlDrvBinary *bin = NULL; MD4Init(&context); MD4Update(&context, buf, len); MD4Final(digest, &context); if (!(bin = driver_alloc_binary(16))) { driver_send_error(md4, &am_enomem); } else { memcpy(bin->orig_bytes, digest, 16); driver_send_bin(md4, bin, 16); driver_free_binary(bin); } return; }
void es_waitEvent2(ErlDrvPort port, ErlDrvTermData caller) { SDL_Event event; ErlDrvBinary * bin; ErlDrvTermData rt[8]; char *bp, *start; int sz; bin = driver_alloc_binary(MAX_EVENT_SIZE); bp = start = bin->orig_bytes; SDL_WaitEvent(&event); bp = encode_event(&event, bp); sz = bp-start; rt[0] = ERL_DRV_ATOM; rt[1]=driver_mk_atom((char *) "_esdl_result_"); rt[2] = ERL_DRV_BINARY; rt[3] = (ErlDrvTermData) bin; rt[4] = sz; rt[5] = 0; rt[6] = ERL_DRV_TUPLE; rt[7] = 2; driver_send_term(port,caller,rt,8); driver_free_binary(bin); }
static void audio_async_decode(void *async_data){ H264Frame *frame = (H264Frame *)async_data; H264Decoder *handle = frame->decoder; int16_t *outbuf=NULL; int len; int size_out; outbuf=av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); AVPacket avpkt; avpkt.data = (uint8_t *)frame->h264->orig_bytes; avpkt.size = frame->h264->orig_size; size_out = AVCODEC_MAX_AUDIO_FRAME_SIZE*2; len = avcodec_decode_audio3(handle->dec, outbuf, &size_out,&avpkt); if(len == -1) { av_free(outbuf); return; }; frame->sample = driver_alloc_binary(size_out); memcpy(frame->sample->orig_bytes,outbuf,size_out); frame->sample->orig_size = size_out; av_free(outbuf); driver_free_binary(frame->h264); }
static void iv_open(t_iconvdrv *iv, char *tocode, char *fromcode) { int len; iconv_t cd; ErlDrvBinary *bin; if ((cd = iconv_open(tocode, fromcode)) == (iconv_t) -1) { driver_send_error(iv, &am_einval); } else { len = sizeof(iconv_t); if (!(bin = driver_alloc_binary(len))) { iconv_close(cd); driver_send_error(iv, &am_enomem); } else { memcpy(bin->orig_bytes, &cd, len); driver_send_bin(iv, bin, len); driver_free_binary(bin); } } return; }
static void iv_conv(t_iconvdrv *iv, iconv_t cd, char *ip, int ileft) { int oleft=OUTBUF_SZ; char *op; int len; ErlDrvBinary *bin; op = &outbuf[0]; /* Reset cd to initial state */ iconv(cd, NULL, NULL, NULL, NULL); if (iconv(cd, &ip, &ileft, &op, &oleft) == (size_t) -1) { if (errno == EILSEQ) driver_send_error(iv, &am_eilseq); else if (errno == EINVAL) driver_send_error(iv, &am_einval); else if (errno == E2BIG) driver_send_error(iv, &am_e2big); else driver_send_error(iv, &am_unknown); } else if (ileft == 0) { len = OUTBUF_SZ - oleft; if (!(bin = driver_alloc_binary(len))) { driver_send_error(iv, &am_enomem); } else { memcpy(bin->orig_bytes, &outbuf[0], len); driver_send_bin(iv, bin, len); driver_free_binary(bin); } } return; }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ static void zmqcb_free_binary(void* /*data*/, void* hint) { ErlDrvBinary* bin = (ErlDrvBinary*)hint; driver_free_binary(bin); }
static void uvc_drv_input(ErlDrvData handle, ErlDrvEvent io_event) { Uvc* d = (Uvc*) handle; struct v4l2_buffer buf; memset(&buf, 0, sizeof buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; int ret = ioctl(d->fd, VIDIOC_DQBUF, &buf); if(ret < 0) { driver_failure_posix(d->port, errno); return; } ErlDrvBinary* bin; size_t len; if(d->pixelformat == V4L2_PIX_FMT_YUYV) { len = d->width*d->height*3/2; bin = driver_alloc_binary(len); if(!d->scale_ctx) d->scale_ctx = sws_getContext( d->width, d->height, PIX_FMT_YUYV422, d->width, d->height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL ); int linesize[4] = {d->width*2, 0, 0, 0}; uint8_t *src[4] = {(uint8_t *)d->buffers[buf.index].mem, 0, 0, 0}; int stride_size = d->width*d->height; uint8_t *plane[4] = {(uint8_t *)bin->orig_bytes, (uint8_t *)bin->orig_bytes+stride_size, (uint8_t *)bin->orig_bytes+stride_size+stride_size/4, NULL}; int stride[4] = {d->width, d->width/2, d->width/2, 0}; sws_scale(d->scale_ctx, (const uint8_t * const*)src, linesize, 0, d->height, plane, stride); } else { bin = driver_alloc_binary(buf.bytesused + 1024); len = add_huffman((uint8_t *)bin->orig_bytes, (uint8_t *)d->buffers[buf.index].mem, buf.bytesused); } ErlDrvUInt64 pts = buf.timestamp.tv_sec * 1000 + buf.timestamp.tv_usec / 1000; ErlDrvTermData reply[] = { ERL_DRV_ATOM, driver_mk_atom("uvc"), ERL_DRV_PORT, driver_mk_port(d->port), ERL_DRV_ATOM, driver_mk_atom(d->pixelformat == V4L2_PIX_FMT_YUYV ? "yuv" : "jpeg"), ERL_DRV_UINT64, &pts, ERL_DRV_BINARY, (ErlDrvTermData)bin, (ErlDrvTermData)len, 0, ERL_DRV_TUPLE, 5 }; // fprintf(stderr, "Event in uvc: %lu %u %u\r\n", len, (unsigned)buf.timestamp.tv_sec, (unsigned)buf.timestamp.tv_usec); driver_output_term(d->port, reply, sizeof(reply) / sizeof(reply[0])); driver_free_binary(bin); ret = video_queue_buffer(d, buf.index); if(ret < 0) { driver_failure_posix(d->port, errno); 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 FILE_from_erlangv(ErlDrvData drv_data, ErlIOVec* ev) { Desc *desc = (Desc*) drv_data; SysIOVec *iov = ev->iov; ErlDrvBinary* bin; switch ((&iov[1])->iov_base[0]) { case XX_OPEN: { char buf[BUFSIZ]; char file[BUFSIZ]; /* should be FILENAME_MAX */ char flags[4]; /* at most someething like rb+ */ char* src; char* dst; char* src_end; char* dst_end; int n; if (desc->fp != NULL) { driver_error(desc->port, XX_EINVAL); return; } /* play it safe ? */ n = vec_to_buf(ev, buf, BUFSIZ); src = buf + 1; src_end = buf + n; /* get file name */ dst = file; dst_end = dst + BUFSIZ; /* make room for a '\0' */ while((src < src_end) && (dst < dst_end) && (*src != '\0')) *dst++ = *src++; if ((src == src_end) || (dst == dst_end)) { driver_error(desc->port, XX_EINVAL); } *dst = *src++; /* get flags */ dst = flags; dst_end = dst + 4; while((src < src_end) && (dst < dst_end) && (*src != '\0')) *dst++ = *src++; if (dst == dst_end) { driver_error(desc->port, XX_EINVAL); return; } *dst = '\0'; if ((desc->fp = fopen(file, flags))==NULL) { driver_error(desc->port, errno); return; } driver_ok(desc->port); break; } case XX_WRITE: { int i; iov[1].iov_base++; iov[1].iov_len--; for(i=1; i<ev->vsize; i++) { if (fwrite(iov[i].iov_base, 1, iov[i].iov_len, desc->fp) != iov[i].iov_len) { driver_error(desc->port, errno); return; } } driver_ok(desc->port); break; } case XX_READ: { char ch = XX_VALUE; int rval; int sz = get_int32((&iov[1])->iov_base+1); if ((bin = driver_alloc_binary(sz)) == NULL) { driver_error(desc->port, -1); return; } if ((rval = fread(bin->orig_bytes, 1, sz, desc->fp)) != sz) { if (feof(desc->fp)) { if (rval == 0) { driver_free_binary(bin); driver_eof(desc->port); return; } driver_output_binary(desc->port, &ch, 1,bin, 0, rval); driver_free_binary(bin); return; } driver_free_binary(bin); driver_error(desc->port, errno); return; } driver_output_binary(desc->port, &ch, 1,bin, 0, sz); driver_free_binary(bin); break; } case XX_SEEK: { int offs = get_int32((&iov[1])->iov_base+1); int w = (int) (&iov[1])->iov_base[5]; int whence; switch (w) { case 1: whence = SEEK_SET; break; case 2: whence = SEEK_CUR; break; case 3: whence = SEEK_END; break; } if ((w = fseek(desc->fp, offs, whence)) != 0) { driver_error(desc->port, errno); return; } driver_ok(desc->port); return; } case XX_TELL: { int offs; if ((offs = ftell(desc->fp)) == -1) { driver_error(desc->port, errno); return; } driver_ret32(desc->port, offs); break; } case XX_TRUNCATE: { int fno; int offs; /* is this really safe? */ if (fflush(desc->fp) != 0) { driver_error(desc->port, errno); return; } if ((offs = ftell(desc->fp)) == -1) { driver_error(desc->port, errno); return; } fno = fileno(desc->fp); #ifdef WIN32 if (SetEndOfFile((HANDLE)fno) != 0) { driver_error(desc->port, GetLastError()); return; } #else if (ftruncate(fno, offs) == -1) { driver_error(desc->port, errno); return; } #endif driver_ok(desc->port); return; } case XX_FLUSH: if (fflush(desc->fp) != 0) driver_error(desc->port, errno); else driver_ok(desc->port); break; case XX_OEOF: if (feof(desc->fp)) driver_ret32(desc->port, 1); else driver_ret32(desc->port,0); break; case XX_ERROR: if (ferror(desc->fp)) driver_ret32(desc->port, 1); else driver_ret32(desc->port,0); break; case XX_GETC: { int ch; if ((ch = getc(desc->fp)) == EOF) { if (feof(desc->fp)) { driver_eof(desc->port); return; } driver_error(desc->port, errno); return; } driver_ret32(desc->port, ch); break; } case XX_SET_LINEBUF_SIZE: { int sz = get_int32((&iov[1])->iov_base+1); desc->linebuf_size = sz; driver_ok(desc->port); break; } case XX_GETS: case XX_GETS2: { int rval; long cpos1, cpos2; char header; if ((bin = driver_alloc_binary(desc->linebuf_size)) == NULL) { driver_error(desc->port, -1); return; } if ((cpos1 = ftell(desc->fp)) == -1) { driver_free_binary(bin); driver_error(desc->port, errno); return; } if ((fgets(bin->orig_bytes, desc->linebuf_size, desc->fp)) == NULL) { driver_free_binary(bin); if (feof(desc->fp)) { driver_eof(desc->port); return; } driver_error(desc->port, errno); return; } if ((cpos2 = ftell(desc->fp)) == -1) { driver_free_binary(bin); driver_error(desc->port, errno); return; } rval = cpos2 - cpos1; if (bin->orig_bytes[rval-1] == '\n' && bin->orig_bytes[rval] == 0) { header = XX_FLINE; /* GETS keep newline, GETS2 remove newline */ rval = rval - ((&iov[1])->iov_base[0] == XX_GETS ? 0 : 1); } else header = XX_NOLINE; driver_output_binary(desc->port, &header, 1,bin, 0, rval); driver_free_binary(bin); break; } case XX_UNGETC: { int ch = (&iov[1])->iov_base[1]; if (ungetc(ch, desc->fp) == EOF) driver_error(desc->port, errno); else driver_ok(desc->port); break; } default: #ifdef DEBUG fprintf(stderr, "Unknown opcode %c\n\r", ((&iov[1])->iov_base[0])); #endif driver_error(desc->port, XX_EINVAL); break; } }
static void iv_conv(t_iconvdrv *iv, iconv_t cd, char *ip, size_t ileft, char ignore) { size_t oleft=ileft; char *op, *buf; int olen = ileft; ErlDrvBinary *bin; /* malloc enough for the input size, * with the assumption that the output length will be close to the input * length. This isn't always the case, but we realloc on E2BIG below. */ buf = malloc(olen); if (!buf) { driver_send_error(iv, &am_enomem); return; } op = buf; /* Reset cd to initial state */ iconv(cd, NULL, NULL, NULL, NULL); while (iconv(cd, &ip, &ileft, &op, &oleft) == (size_t) -1 && !(ignore && errno == EILSEQ)) { if (errno == EILSEQ) { driver_send_error(iv, &am_eilseq); } else if (errno == EINVAL) { driver_send_error(iv, &am_einval); } else if (errno == E2BIG) { char *newbuf; int newolen = olen + ileft + oleft; /* allocate as much additional space as iconv says we need */ newbuf = realloc(buf, newolen); if (!newbuf) { driver_send_error(iv, &am_enomem); goto free_and_return; } op = newbuf + (op - buf); buf = newbuf; olen = newolen; oleft = olen - (op - buf); /* keep going */ continue; } else { driver_send_error(iv, &am_unknown); } goto free_and_return; } if (ileft == 0) { /* find the length of the result */ olen = op - buf; if (!(bin = driver_alloc_binary(olen))) { driver_send_error(iv, &am_enomem); } else { memcpy(bin->orig_bytes, buf, olen); driver_send_bin(iv, bin, olen); driver_free_binary(bin); } } free_and_return: /* To ensure cleanup, this is the only exit point after an initial * successful malloc. */ free(buf); return; }
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]); } }
int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller) { ErlDrvBinary* bin; int i; GLdouble* new_vertices; int *vertices; int num_vertices; GLdouble *n; int n_pos, AP, res; num_vertices = * (int *) buff; buff += 8; /* Align */ n = (double *) buff; buff += 8*3; bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble)); new_vertices = tess_coords = (double *) bin->orig_bytes; memcpy(tess_coords,buff,num_vertices*3*sizeof(GLdouble)); tess_alloc_vertex = tess_coords + num_vertices*3; #if 0 fprintf(stderr, "n=%d\r\n", num_vertices); #endif vertices = (int *) driver_alloc(sizeof(int) * 16*num_vertices); tess_vertices = vertices; gluTessNormal(tess, n[0], n[1], n[2]); gluTessBeginPolygon(tess, 0); gluTessBeginContour(tess); for (i = 0; i < num_vertices; i++) { gluTessVertex(tess, tess_coords+3*i, tess_coords+3*i); } gluTessEndContour(tess); gluTessEndPolygon(tess); n_pos = (tess_vertices - vertices); AP = 0; ErlDrvTermData *rt; rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+n_pos*2)); rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_"); for(i=0; i < n_pos; i++) { rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) vertices[i]; }; rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = n_pos+1; rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin; rt[AP++] = (tess_alloc_vertex-new_vertices)*sizeof(GLdouble); rt[AP++] = 0; rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin} rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple res = driver_send_term(port,caller,rt,AP); /* fprintf(stderr, "List %d: %d %d %d \r\n", */ /* res, */ /* n_pos, */ /* (tess_alloc_vertex-new_vertices)*sizeof(GLdouble), */ /* num_vertices*6*sizeof(GLdouble)); */ driver_free_binary(bin); driver_free(vertices); driver_free(rt); return 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; } }
static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { ZLibData* d = (ZLibData*)drv_data; int res; switch(command) { case DEFLATE_INIT: if (len != 4) goto badarg; if (d->state != ST_NONE) goto badarg; res = deflateInit(&d->s, i32(buf)); if (res == Z_OK) { d->state = ST_DEFLATE; d->want_crc = 0; d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); case DEFLATE_INIT2: { int wbits; if (len != 20) goto badarg; if (d->state != ST_NONE) goto badarg; wbits = i32(buf+8); res = deflateInit2(&d->s, i32(buf), i32(buf+4), wbits, i32(buf+12), i32(buf+16)); if (res == Z_OK) { d->state = ST_DEFLATE; d->want_crc = (wbits < 0); d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); } case DEFLATE_SETDICT: if (d->state != ST_DEFLATE) goto badarg; res = deflateSetDictionary(&d->s, (unsigned char*)buf, len); if (res == Z_OK) { return zlib_value(d->s.adler, rbuf, rlen); } else { return zlib_return(res, rbuf, rlen); } case DEFLATE_RESET: if (len != 0) goto badarg; if (d->state != ST_DEFLATE) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = deflateReset(&d->s); return zlib_return(res, rbuf, rlen); case DEFLATE_END: if (len != 0) goto badarg; if (d->state != ST_DEFLATE) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = deflateEnd(&d->s); d->state = ST_NONE; return zlib_return(res, rbuf, rlen); case DEFLATE_PARAMS: if (len != 8) goto badarg; if (d->state != ST_DEFLATE) goto badarg; res = deflateParams(&d->s, i32(buf), i32(buf+4)); return zlib_return(res, rbuf, rlen); case DEFLATE: if (d->state != ST_DEFLATE) goto badarg; if (len != 4) goto badarg; res = zlib_deflate(d, i32(buf)); return zlib_return(res, rbuf, rlen); case INFLATE_INIT: if (len != 0) goto badarg; if (d->state != ST_NONE) goto badarg; res = inflateInit(&d->s); if (res == Z_OK) { d->state = ST_INFLATE; d->inflate_eos_seen = 0; d->want_crc = 0; d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); case INFLATE_INIT2: { int wbits; if (len != 4) goto badarg; if (d->state != ST_NONE) goto badarg; wbits = i32(buf); res = inflateInit2(&d->s, wbits); if (res == Z_OK) { d->state = ST_INFLATE; d->inflate_eos_seen = 0; d->want_crc = (wbits < 0); d->crc = crc32(0L, Z_NULL, 0); } return zlib_return(res, rbuf, rlen); } case INFLATE_SETDICT: if (d->state != ST_INFLATE) goto badarg; res = inflateSetDictionary(&d->s, (unsigned char*)buf, len); return zlib_return(res, rbuf, rlen); case INFLATE_SYNC: if (d->state != ST_INFLATE) goto badarg; if (len != 0) goto badarg; if (driver_sizeq(d->port) == 0) { res = Z_BUF_ERROR; } else { int vlen; SysIOVec* iov = driver_peekq(d->port, &vlen); d->s.next_in = iov[0].iov_base; d->s.avail_in = iov[0].iov_len; res = inflateSync(&d->s); } return zlib_return(res, rbuf, rlen); case INFLATE_RESET: if (d->state != ST_INFLATE) goto badarg; if (len != 0) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = inflateReset(&d->s); d->inflate_eos_seen = 0; return zlib_return(res, rbuf, rlen); case INFLATE_END: if (d->state != ST_INFLATE) goto badarg; if (len != 0) goto badarg; driver_deq(d->port, driver_sizeq(d->port)); res = inflateEnd(&d->s); if (res == Z_OK && d->inflate_eos_seen == 0) { res = Z_DATA_ERROR; } d->state = ST_NONE; return zlib_return(res, rbuf, rlen); case INFLATE: if (d->state != ST_INFLATE) goto badarg; if (len != 4) goto badarg; res = zlib_inflate(d, i32(buf)); if (res == Z_NEED_DICT) { return zlib_value2(3, d->s.adler, rbuf, rlen); } else { return zlib_return(res, rbuf, rlen); } case GET_QSIZE: return zlib_value(driver_sizeq(d->port), rbuf, rlen); case GET_BUFSZ: return zlib_value(d->binsz_need, rbuf, rlen); case SET_BUFSZ: { int need; if (len != 4) goto badarg; need = i32(buf); if ((need < 16) || (need > 0x00ffffff)) goto badarg; if (d->binsz_need != need) { d->binsz_need = need; if (d->bin != NULL) { if (d->s.avail_out == d->binsz) { driver_free_binary(d->bin); d->bin = NULL; d->binsz = 0; } else zlib_output(d); } } return zlib_return(Z_OK, rbuf, rlen); } case CRC32_0: return zlib_value(d->crc, rbuf, rlen); case CRC32_1: { uLong crc = crc32(0L, Z_NULL, 0); crc = crc32(crc, (unsigned char*) buf, len); return zlib_value(crc, rbuf, rlen); } case CRC32_2: { uLong crc; if (len < 4) goto badarg; crc = (unsigned int) i32(buf); crc = crc32(crc, (unsigned char*) buf+4, len-4); return zlib_value(crc, rbuf, rlen); } case ADLER32_1: { uLong adler = adler32(0L, Z_NULL, 0); adler = adler32(adler, (unsigned char*) buf, len); return zlib_value(adler, rbuf, rlen); } case ADLER32_2: { uLong adler; if (len < 4) goto badarg; adler = (unsigned int) i32(buf); adler = adler32(adler, (unsigned char*) buf+4, len-4); return zlib_value(adler, rbuf, rlen); } case CRC32_COMBINE: { uLong crc, crc1, crc2, len2; if (len != 12) goto badarg; crc1 = (unsigned int) i32(buf); crc2 = (unsigned int) i32(buf+4); len2 = (unsigned int) i32(buf+8); crc = crc32_combine(crc1, crc2, len2); return zlib_value(crc, rbuf, rlen); } case ADLER32_COMBINE: { uLong adler, adler1, adler2, len2; if (len != 12) goto badarg; adler1 = (unsigned int) i32(buf); adler2 = (unsigned int) i32(buf+4); len2 = (unsigned int) i32(buf+8); adler = adler32_combine(adler1, adler2, len2); return zlib_value(adler, rbuf, rlen); } } badarg: errno = EINVAL; return zlib_return(Z_ERRNO, rbuf, rlen); }
// Retrieve a record from the database, if it exists static void get(bdb_drv_t *bdb_drv, ErlIOVec *ev) { ErlDrvBinary* input = ev->binv[1]; ErlDrvBinary *output_bytes; char *bytes = input->orig_bytes; char *key_bytes = bytes+1; DB *db = bdb_drv->db; DBT key; DBT value; int status; bzero(&key, sizeof(DBT)); bzero(&value, sizeof(DBT)); key.data = key_bytes; key.size = KEY_SIZE; // Have BerkeleyDB allocate memory big enough to store the value value.flags = DB_DBT_MALLOC; // Don't forget to free it later // Retrieve the record status = db->get(db, NULL, &key, &value, 0); if(status == 0) { // Get went OK // Copy the record value to an output structure to return to Erlang VM output_bytes = driver_alloc_binary(value.size); output_bytes->orig_size = value.size; memcpy(output_bytes->orig_bytes, value.data, value.size); free(value.data); // TODO:Figure out if we can somehow use this original memory without recopying a la: //binary->orig_bytes = (char *)&data.data; // Returns tuple {ok, Data} ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok"), ERL_DRV_BINARY, (ErlDrvTermData) output_bytes, output_bytes->orig_size, 0, ERL_DRV_TUPLE, 2}; driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); driver_free_binary(output_bytes); } else { // there was an error char *error_reason; switch(status) { case DB_LOCK_DEADLOCK: error_reason = "deadlock"; break; case DB_SECONDARY_BAD: error_reason = "bad_secondary_index"; break; case ENOMEM: error_reason = "insufficient_memory"; break; case EINVAL: error_reason = "bad_flag"; break; case DB_RUNRECOVERY: error_reason = "run_recovery"; break; default: error_reason = "unknown"; } // Return tuple {error, Reason} ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), ERL_DRV_ATOM, driver_mk_atom(error_reason), ERL_DRV_TUPLE, 2}; driver_output_term(bdb_drv->port, spec, sizeof(spec) / sizeof(spec[0])); } }