func (e *clEngine) Compile(cvdDir string) error { e.mtx.Lock() defer e.mtx.Unlock() if e.IsCompiled() { return ErrAlreadyCompiled } // Create new engine e.engine = C.cl_engine_new() if e.engine == nil { return errors.New("failed to create new clamav engine") } // Load signatures var ret C.int var sigs C.uint = 0 ret = C.cl_load(C.CString(cvdDir), e.engine, &sigs, C.CL_DB_STDOPT) if ret != C.CL_SUCCESS { return fmt.Errorf("could not load vcds: %s", C.GoString(C.cl_strerror(ret))) } // Compile engine ret = C.cl_engine_compile(e.engine) if ret != C.CL_SUCCESS { return fmt.Errorf("could not compile engine: %s", C.GoString(C.cl_strerror(ret))) } atomic.StoreInt32(&e.compiled, 1) return nil }
func (e *clEngine) Scan(file *os.File) error { e.mtx.Lock() defer e.mtx.Unlock() var ret C.int var fd C.int = C.int(file.Fd()) var virname *C.char var size C.ulong = 0 // Scan file var virName string ret = C.cl_scandesc(fd, &virname, &size, e.engine, C.CL_SCAN_STDOPT) if ret == C.CL_VIRUS { virName = C.GoString(virname) } else if ret == C.CL_CLEAN { // do nothing } else { return fmt.Errorf("error scanning file: %s", C.GoString(C.cl_strerror(ret))) } if len(virName) > 0 { return &VirusError{ VirusName: virName, BytesScanned: uint64(size * C.CL_COUNT_PRECISION), } } return nil }
func init() { // Prepare libclamav var ret C.int ret = C.cl_init(C.CL_INIT_DEFAULT) if ret != C.CL_SUCCESS { panic("cannot initialize clamav:" + C.GoString(C.cl_strerror(ret))) } }
// String converts the error code to human readable format func (e ErrorCode) String() string { return C.GoString(C.cl_strerror(C.int(e))) }
// Strerror converts LibClam error codes to human readable format func StrError(errno ErrorCode) string { return C.GoString(C.cl_strerror(C.int(errno))) }