Beispiel #1
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);
}
Beispiel #2
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;
    }
}
Beispiel #3
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;
    }
	
	
}