Keywords: clamdoc

Next: Database reloading Up: LibClamAV Previous: LibClamAV Contents

## General API

Every program based on libclamav must include the `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 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 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_RAW
  It does nothing. Please use it (alone) if you don't want to scan any special files.
- CL_ARCHIVE
  This flag enables the transparent archive scanning.
- CL_DISABLERAR
  Disables the built-in RAR unpacker which is known to cause memory leaks.
- CL_ENCRYPTED
  Marks encrypted archives as viruses (Enccrypted.Zip, Encrypted.RAR).
- CL_MAIL
  Required to scan various types of mail files.
- CL_OLE2
  Enables support for Microsoft Office document files.

All functions return 0 (`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 -lclamav

Enjoy !

Next: Database reloading Up: LibClamAV Previous: LibClamAV Contents