int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
{
	int ret = CL_CLEAN;
	unsigned int i = 0, j = 0, viruses_found = 0;
	struct cli_ac_data mdata;
	struct cli_matcher *groot, *troot = NULL;
	const char *virname = NULL;
	const struct cl_engine *engine=ctx->engine;

    if(!engine) {
	cli_errmsg("cli_scanbuff: engine == NULL\n");
	return CL_ENULLARG;
    }

    groot = engine->root[0]; /* generic signatures */

    if(ftype) {
        for(i = 1; i < CLI_MTARGETS; i++) {
            for (j = 0; j < cli_mtargets[i].target_count; ++j) {
                if(cli_mtargets[i].target[j] == ftype) {
                    troot = ctx->engine->root[i];
                    break;
                }
            }
            if (troot) break;
        }
    }

    if(troot) {

	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
	    return ret;

	ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, PCRE_SCAN_BUFF, NULL, *ctx->fmap, NULL, NULL, ctx);

	if(!acdata)
	    cli_ac_freedata(&mdata);

	if(ret == CL_EMEM)
	    return ret;
	if(ret == CL_VIRUS) {
	    viruses_found = 1;
	    if(ctx && !SCAN_ALL) {
		return ret;
	    }
	}
    }

    virname = NULL;

    if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
	return ret;

    ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, PCRE_SCAN_BUFF, NULL, *ctx->fmap, NULL, NULL, ctx);

    if(!acdata)
	cli_ac_freedata(&mdata);

    if(viruses_found)
	return CL_VIRUS;
    return ret;
}
int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata)
{
	int ret = CL_CLEAN;
	unsigned int i = 0, j = 0, viruses_found = 0;
	struct cli_ac_data mdata;
	struct cli_matcher *groot, *troot = NULL;
	const char *virname = NULL;
	const struct cl_engine *engine=ctx->engine;

    if(!engine) {
	cli_errmsg("cli_scanbuff: engine == NULL\n");
	return CL_ENULLARG;
    }

    groot = engine->root[0];  

    if(ftype) {
        for(i = 1; i < CLI_MTARGETS; i++) {
            for (j = 0; j < cli_mtargets[i].target_count; ++j) {
                if(cli_mtargets[i].target[j] == ftype) {
                    troot = ctx->engine->root[i];
                    break;
                }
            }
            if (troot) break;
        }
    }

    if(troot) {

	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
	    return ret;

	ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, PCRE_SCAN_BUFF, NULL, *ctx->fmap, NULL, NULL, ctx);

	if(!acdata)
	    cli_ac_freedata(&mdata);

	if(ret == CL_EMEM)
	    return ret;
	if(ret == CL_VIRUS) {
	    viruses_found = 1;
	    if(ctx && !SCAN_ALL) {
		return ret;
	    }
	}
    }

    virname = NULL;

    if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
	return ret;

    ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, PCRE_SCAN_BUFF, NULL, *ctx->fmap, NULL, NULL, ctx);

    if(!acdata)
	cli_ac_freedata(&mdata);

    if(viruses_found)
	return CL_VIRUS;
    return ret;
}