#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); 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 7 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 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:
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:
void cl_buildtrie(struct cl_node *root);In our example:
cl_buildtrie(root);OK, now you can scan a buffer, a descriptor or a file with:
int cl_scanbuff(const char *buffer, unsigned int length, char **virname, const struct cl_node *root); int cl_scandesc(int desc, char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options); int cl_scanfile(const char *filename, 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. virname 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; int maxfiles; long int maxfilesize; };The last argument configures scan engine. Currently it supports CL_ARCHIVE (enables archive scanning), CL_RAW (disables archive scanning) and CL_MAIL (enables mbox and Maildir scanning) and CL_DISABLERAR (disables the built-in RAR unpacker which leaks like hell). These functions return 0 (CL_CLEAN) when no virus is found, CL_VIRUS when virus is found and other value on failure.
struct cl_limits limits; 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; if((ret = cl_scanfile("/home/zolw/test", &virname, NULL, root, &limits, CL_ARCHIVE)) == 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). Program based on libclamav must be linked against it:
gcc -Wall ex1.c -o ex1 -lclamavEnjoy !