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 !
Tomasz Kojm 2004-07-22