Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
0
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);
    }
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
/*
 * 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);
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
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);
}
Exemplo n.º 14
0
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);
}
Exemplo n.º 15
0
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);
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
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);
}
Exemplo n.º 18
0
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);
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
static void
zmqcb_free_binary(void* /*data*/, void* hint)
{
    ErlDrvBinary* bin = (ErlDrvBinary*)hint;
    driver_free_binary(bin);
}
Exemplo n.º 22
0
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;
  }
}
Exemplo n.º 23
0
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;
    }
}
Exemplo n.º 24
0
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;
    }
	
	
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
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]);
    }
}
Exemplo n.º 27
0
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;
}
Exemplo n.º 28
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;
    }
}
Exemplo n.º 29
0
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);
}
Exemplo n.º 30
0
// 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]));
  }
}