clamav.h
header
file:
#include <clamav.h>A first step is to initialize the scanning engine. There are three functions available:
int cl_loaddb(const char *filename, struct cl_node **root, int *virnum); int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum); const char *cl_retdbdir(void);
cl_loaddb()
loads a particular database, cl_loaddbdir()
loads all .cvd (and older .db, .db2) databases from a
directory dirname
. cl_retdbdir()
returns a hardcoded
database directory path. Initial internal database (Aho-Corasick tree,
trie; see 6.3) will be saved under root
and a number of
signatures loaded will be added 8 to virnum
. Pointer to the trie
must initially point to NULL. If you don't care about number of signatures
pass NULL as a third argument. cl_loaddb
functions return 0 on
success and an other value on failure.
struct cl_node *root = NULL; int ret; ret = cl_loaddbdir(cl_retdbdir(), &root, NULL);There's an elegant way to print libclamav's error codes:
const char *cl_strerror(int clerror);
cl_strerror()
returns a (statically allocated) string describing
a clerror
code:
if(ret) { printf("cl_loaddbdir() error: %s\n", cl_strerror(ret)); exit(1); }When database is loaded you must build the final trie with:
int cl_buildtrie(struct cl_node *root);In our example:
if((ret = cl_buildtrie(root))) printf("cl_buildtrie() error: %s\n", cl_strerror(ret));Now you can scan a buffer, a descriptor or a file with:
int cl_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root); int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options); int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options);All the functions save a virus name address under
virname
pointer.
It points to a name in the trie structure thus it can't be released
directly. cl_scandesc()
and cl_scanfile()
can
increase the scanned
value in CL_COUNT_PRECISION
units,
they also support archive limits:
struct cl_limits { int maxreclevel; /* maximal recursion level */ int maxfiles; /* maximal number of files to be * scanned within an archive */ int maxratio; /* maximal compression ratio */ short archivememlim; /* limit memory usage for bzip2 (0/1) */ long int maxfilesize; /* files in an archive larger than * this value will not be scanned */ };The last argument in the
cl_scan
family configures the scan
engine. It supports the following flags:
CL_CLEAN
) if the file is clean,
CL_VIRUS
when virus is detected and an other value on failure.
struct cl_limits limits; const char *virname; memset(&limits, 0, sizeof(struct cl_limits)); /* maximal number of files in archive */; limits.maxfiles = 1000 /* maximal archived file size == 10 MB */ limits.maxfilesize = 10 * 1048576; /* maximal recursion level */ limits.maxreclevel = 5; /* maximal compression ratio */ limits.maxratio = 200; /* disable memory limit for bzip2 scanner */ limits.archivememlim = 0; if((ret = cl_scanfile("/home/zolw/test", &virname, NULL, root, &limits, CL_ARCHIVE | CL_MAIL | CL_OLE2)) == CL_VIRUS) { printf("Detected %s virus.\n", virname); } else { printf("No virus detected.\n"); if(ret != CL_CLEAN) printf("Error: %s\n", cl_strerror(ret)); }Release the trie if you no longer need it:
void cl_freetrie(struct cl_node *root);You will find an example scanner in clamav sources (/example). All programs based on libclamav must be linked against it:
gcc -Wall ex1.c -o ex1 -lclamavEnjoy !