Exemple #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;
}
Exemple #2
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;
}
Exemple #3
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;
}
Exemple #4
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;
}
Exemple #5
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;
}