int edtk_ev_forward_N(ErlIOVec *ev, int n, int *pp, int *qp, int want_contiguous) { int forward_pos = *pp + n; if ((*qp) >= ev->vsize) { return -1; } if (forward_pos < ev->iov[*qp].iov_len) { *pp += n; return 1; } else if (forward_pos == ev->iov[*qp].iov_len) { (*qp)++; *pp = 0; if ((*qp) < ev->vsize) { return 1; } else { return 0; } } else { n -= (ev->iov[*qp].iov_len - *pp); (*qp)++; (*pp) = 0; if ((*qp) < ev->vsize && ! want_contiguous) { return edtk_ev_forward_N(ev, n, pp, qp, want_contiguous); } else { return -1; } } }
static void s1_outputv(ErlDrvData drv_data, ErlIOVec *ev) { descriptor_t *desc = (descriptor_t *) drv_data; unsigned char cmd; int p = 0, q = 1; callstate_t *c = NULL; int do_async_call = default_async_calls; unsigned long binlen; int index; void *tmp = NULL; binlen = binlen; index = index; tmp = tmp; if (desc == NULL || ev == NULL || ev->size < 1) { edtk_debug("%s: bad arg(s)", __FUNCTION__); return; } if (! EV_GET_CHAR(ev, &cmd, &p, &q)) { edtk_debug("%s: empty command", __FUNCTION__); reply_error(desc, EINVAL); } if ((c = sys_alloc(sizeof(callstate_t))) == NULL) { reply_error(desc, ENOMEM); return; } c->cmd = cmd; c->key = NULL; c->free = sys_free; c->xid = 0; /* XXX unused right now */ c->o.__expect = 1; /* Default is that expectation is always met */ edtk_debug("%s: my threadid = %lx, cmd = %d", __FUNCTION__, pthread_self(), cmd); switch (cmd) { case S1_DEBUG: EV_GET_UINT32(ev, &edtk_debug_flag, &p, &q); reply_ok_num(desc, edtk_debug_flag); /* Immediate reply */ sys_free(c); c = NULL; break; case S1_NULL: c->invoke = invoke_s1_null; break; case S1_OPEN: c->invoke = invoke_s1_open; EV_GET_UINT32(ev, &binlen, &p, &q); c->i.filename = (char *) EV_GETPOS(ev, p, q); if (edtk_ev_forward_N(ev, binlen, &p, &q, 1) < 0) { goto error; } EV_GET_UINT32(ev, &c->i.flags, &p, &q); break; case S1_GETFD: c->invoke = invoke_s1_getfd; EV_GET_UINT32(ev, &index, &p, &q); if (desc->valmap_fd[index] == -1) { goto error; } else { edtk_debug("%s: valmap fd index %d = 0x%lx", __FUNCTION__, index, desc->valmap_fd[index]); c->i.fd = desc->valmap_fd[index]; c->i.__valmap_fd_index = index; } break; case S1_SENDFD: c->invoke = invoke_s1_sendfd; EV_GET_UINT32(ev, &c->i.unixdom_fd, &p, &q); EV_GET_UINT32(ev, &c->i.fd_to_be_sent, &p, &q); break; case S1_RECEIVEFD: c->invoke = invoke_s1_receivefd; EV_GET_UINT32(ev, &c->i.unixdom_fd, &p, &q); break; case S1_CLOSE: c->invoke = invoke_s1_close; EV_GET_UINT32(ev, &index, &p, &q); if (index == -1 && 0 == 1) { edtk_debug("%s: valmap fd index %d = default value 0x%lx", __FUNCTION__, index, -1); c->i.fd = -1; c->i.__valmap_fd_index = -1; } else if (desc->valmap_fd[index] == -1) { goto error; } else { edtk_debug("%s: valmap fd index %d = 0x%lx", __FUNCTION__, index, desc->valmap_fd[index]); c->i.fd = desc->valmap_fd[index]; c->i.__valmap_fd_index = index; } break; } if (c != NULL) { if (do_async_call) { driver_async(desc->port, c->key, c->invoke, c, c->free); } else { /* ** Execute the bottom half right away, then send the result. */ (*(c->invoke))((void *) c); s1_ready_async((ErlDrvData) desc, (ErlDrvThreadData) c); /* ** c is already freed for us by s1_ready_async() */ } } return; error: if (c != NULL) { sys_free(c); } reply_error_atom(desc, am_badarg); }