Commit d479ebbf6 for clamav.net

commit d479ebbf6aa0883612ea07b14b6f444750dd6179
Author: Jonas Zaddach <5988756+zaddach@users.noreply.github.com>
Date:   Mon Oct 20 12:13:19 2025 +0200

    Remove ex_prescan_callback and ex_file_inspection_callback examples

    The prescan and file_inspection callbacks are deprecated and should not be used.
    They are replaced by a more unified scan callback system which is demonstrated in
    ex_scan_callbacks.c.

diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 9bfa2049b..68554f3ad 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -31,32 +31,6 @@ if(ENABLE_STATIC_LIB)
     install(TARGETS ex_basic_scandesc_static)
 endif()

-add_executable(ex_prescan_callback)
-target_sources(ex_prescan_callback
-    PRIVATE   ex_prescan_callback.c)
-set_target_properties(ex_prescan_callback PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}")
-target_link_libraries(ex_prescan_callback
-    PRIVATE
-        ClamAV::libclamav)
-if(LLVM_FOUND)
-    target_link_directories( ex_prescan_callback PUBLIC ${LLVM_LIBRARY_DIRS} )
-    target_link_libraries( ex_prescan_callback PUBLIC ${LLVM_LIBRARIES} )
-endif()
-install(TARGETS ex_prescan_callback)
-
-add_executable(ex_file_inspection_callback)
-target_sources(ex_file_inspection_callback
-    PRIVATE   ex_file_inspection_callback.c)
-set_target_properties(ex_file_inspection_callback PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}")
-target_link_libraries(ex_file_inspection_callback
-    PRIVATE
-        ClamAV::libclamav)
-if(LLVM_FOUND)
-    target_link_directories( ex_file_inspection_callback PUBLIC ${LLVM_LIBRARY_DIRS} )
-    target_link_libraries( ex_file_inspection_callback PUBLIC ${LLVM_LIBRARIES} )
-endif()
-install(TARGETS ex_file_inspection_callback)
-
 add_executable(ex_scan_callbacks)
 target_sources(ex_scan_callbacks
     PRIVATE   ex_scan_callbacks.c)
diff --git a/examples/ex_file_inspection_callback.c b/examples/ex_file_inspection_callback.c
deleted file mode 100644
index 9609da4cb..000000000
--- a/examples/ex_file_inspection_callback.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- *  Copyright (C) 2020-2025 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- *  MA 02110-1301, USA.
- */
-
-/*
- * This example demonstrates using callbacks to record information about each
- * file found during a recursive scan.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <clamav.h>
-
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#endif
-
-/** Max # of bytes to show for archive inspection preview */
-#define MAX_PREVIEW 10
-
-cl_error_t inspection_callback(
-    int fd,
-    const char *type,
-    const char **ancestors, // array of null-terminated strings, array size == recursion_level
-    size_t parent_file_size,
-    const char *file_name,
-    size_t file_size,
-    const char *file_buffer,
-    uint32_t recursion_level,
-    uint32_t attributes, // E.g.: was normalized, decrypted, etc. See LAYER_ATTRIBUTES_* flags in clamav.h
-    void *context)       // Could be used to retrieve / store contextual information for app
-{
-    size_t i = 0;
-
-    // printf("Message: %s\n", (char *)context.blah);
-    UNUSEDPARAM(context);
-
-    printf("ancestors:          ");
-    for (i = 0; i < recursion_level; i++) {
-        printf("%s", ancestors[i]);
-        if (i + 1 < recursion_level) {
-            printf(" > ");
-        }
-    }
-    printf("\n");
-    printf("parent size:        %zu\n", parent_file_size);
-    printf("file name:          %s\n", file_name);
-    printf("file desc:          %d\n", fd);
-    printf("file size:          %zu\n", file_size);
-    printf("file type:          %s\n", type);
-    printf("recursion level:    %u\n", recursion_level);
-    printf("decrypted:          %s\n", attributes & LAYER_ATTRIBUTES_DECRYPTED ? "yes" : "no");
-    printf("normalized:         %s\n", attributes & LAYER_ATTRIBUTES_NORMALIZED ? "yes" : "no");
-    printf("file preview: ");
-    for (i = 0; i < MIN(file_size, MAX_PREVIEW); i++) {
-        uint8_t byte = file_buffer[i];
-        printf("%02x ", byte);
-    }
-    printf("\n\n");
-
-    return CL_CLEAN; /* keep scanning */
-}
-
-cl_error_t post_callback(
-    int fd,
-    int result,
-    const char *virname,
-    void *context) // Could be used to retrieve / store contextual information for app
-{
-    (void)fd;
-    (void)context;
-
-    printf("result:             %d\n", result);
-    printf("virname:            %s\n", virname);
-    printf("\n\n");
-
-    return CL_CLEAN; // respect the original result
-}
-
-/*
- * Exit codes:
- *  0: clean
- *  1: infected
- *  2: error
- */
-
-int main(int argc, char **argv)
-{
-    int status     = 2;
-    cl_error_t ret = CL_ERROR;
-
-    int db_fd     = -1;
-    int target_fd = -1;
-
-    unsigned long int size = 0;
-    long double mb;
-    const char *virname;
-    const char *filename;
-    struct cl_engine *engine = NULL;
-    struct cl_scan_options options;
-    char database_filepath[256];
-    bool created_database = false;
-
-    STATBUF st;
-    char *mem = NULL;
-    ssize_t bytes_read;
-    cl_fmap_t *map = NULL;
-
-    if (argc != 2) {
-        printf("Usage: %s file\n", argv[0]);
-        return 2;
-    }
-
-    filename = argv[1];
-
-    if ((target_fd = open(argv[1], O_RDONLY)) == -1) {
-        printf("Can't open file %s\n", argv[1]);
-        goto done;
-    }
-
-    if (FSTAT(target_fd, &st)) {
-        printf("fmap: fstat failed\n");
-        goto done;
-    }
-
-    if (NULL == (mem = malloc((size_t)st.st_size))) {
-        printf("malloc failed, buffer size: %zu\n", (size_t)st.st_size);
-        goto done;
-    }
-
-    bytes_read = read(target_fd, mem, (size_t)st.st_size);
-    if (bytes_read != (ssize_t)st.st_size) {
-        printf("read failed, buffer size: %zu\n", (size_t)st.st_size);
-        goto done;
-    }
-
-    map = cl_fmap_open_memory(mem, (size_t)st.st_size);
-
-    if (CL_SUCCESS != (ret = cl_init(CL_INIT_DEFAULT))) {
-        printf("Can't initialize libclamav: %s\n", cl_strerror(ret));
-        goto done;
-    }
-
-    if (!(engine = cl_engine_new())) {
-        printf("Can't create new engine\n");
-        goto done;
-    }
-
-    /* Example version macro usage to determine if new feature is available */
-#if defined(LIBCLAMAV_VERSION_NUM) && (LIBCLAMAV_VERSION_NUM >= 0x090400)
-    /* Example feature usage lowering max scan time to 15 seconds. */
-    cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, 15000);
-#endif
-    cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, 1024 /*MB*/ * 1024 /*KB*/ * 1024 /*bytes*/);
-    cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, 1024 /*MB*/ * 1024 /*KB*/ * 1024 /*bytes*/);
-
-    /* load a pwdb signature, to demonstrate the "was decrypted" feature */
-#define PWDB_FILENAME "./ex3.pwdb"
-    unsigned int signo = 0;
-    if (-1 == (db_fd = open(PWDB_FILENAME, O_CREAT | O_RDWR, 0600))) {
-        printf("Failed to create ex3.pwdb database\n");
-        goto done;
-    }
-
-#define PWDB_SIGNATURE "SignatureName;Engine:80-1000;0;virus"
-    if (-1 == write(db_fd, PWDB_SIGNATURE, strlen(PWDB_SIGNATURE))) {
-        printf("Failed write to ex3.pwdb database\n");
-        goto done;
-    }
-
-    if (CL_SUCCESS != (ret = cl_load(PWDB_FILENAME, engine, &signo, CL_DB_STDOPT))) {
-        printf("Database load error: %s\n", cl_strerror(ret));
-        goto done;
-    }
-
-    close(db_fd);
-
-    /* build engine */
-    if (CL_SUCCESS != (ret = cl_engine_compile(engine))) {
-        printf("Database initialization error: %s\n", cl_strerror(ret));
-        goto done;
-    }
-
-    /* scan file descriptor */
-    memset(&options, 0, sizeof(struct cl_scan_options));
-    options.parse |= ~0;                           /* enable all parsers */
-    options.general |= CL_SCAN_GENERAL_HEURISTICS; /* enable heuristic alert options */
-    options.general |= CL_SCAN_GENERAL_ALLMATCHES; /* run in all-match mode, so it keeps looking for alerts after the first one */
-
-    options.heuristic |= CL_SCAN_HEURISTIC_ENCRYPTED_ARCHIVE;
-    options.heuristic |= CL_SCAN_HEURISTIC_ENCRYPTED_DOC;
-
-    /*
-     * Set our callbacks for inspecting embedded files during the scan.
-     */
-    cl_engine_set_clcb_file_inspection(engine, &inspection_callback);
-    /*
-     * Set our callbacks for inspecting embedded files during the scan.
-     */
-    cl_engine_set_clcb_post_scan(engine, &post_callback);
-
-    printf("Testing file inspection on FD %d - %s\n", target_fd, filename);
-
-    if (CL_VIRUS == (ret = cl_scanmap_callback(
-                         map,
-                         filename,
-                         &virname,
-                         &size,
-                         engine,
-                         &options,
-                         (void *)"Hello, World!"))) {
-        printf("Virus detected: %s\n", virname);
-    } else {
-        if (ret != CL_CLEAN) {
-            printf("Error: %s\n", cl_strerror(ret));
-            goto done;
-        }
-    }
-    /* calculate size of scanned data */
-    mb = size * (CL_COUNT_PRECISION / 1024) / 1024.0;
-    printf("Data scanned: %2.2Lf MB\n", mb);
-
-    status = ret == CL_VIRUS ? 1 : 0;
-
-done:
-
-    if (NULL != map) {
-        cl_fmap_close(map);
-    }
-    if (NULL != mem) {
-        free(mem);
-    }
-    unlink(PWDB_FILENAME);
-    if (-1 != db_fd) {
-        close(db_fd);
-    }
-    if (-1 != target_fd) {
-        close(target_fd);
-    }
-    if (NULL != engine) {
-        cl_engine_free(engine);
-    }
-    if (true == created_database) {
-        unlink(database_filepath);
-    }
-
-    return status;
-}
diff --git a/examples/ex_prescan_callback.c b/examples/ex_prescan_callback.c
deleted file mode 100644
index 7888ed9a8..000000000
--- a/examples/ex_prescan_callback.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- *  Copyright (C) 2020-2025 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- *  MA 02110-1301, USA.
- */
-
-/*
- * This example demonstrates using callbacks to record information about each
- * file found during a recursive scan.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <clamav.h>
-
-#ifdef _WIN32
-typedef int ssize_t;
-#endif
-
-cl_error_t scan_callback(int fd, const char *type, void *context)
-{
-    char buf[10];
-    ssize_t bytes_read = 0;
-    (void)context; /* Could be used to retrieve/store info */
-
-    printf("fd: %u, type: %s, initial bytes: ", fd, type);
-    if (-1 != (bytes_read = read(fd, &buf, sizeof(buf)))) {
-        /* Was able to read a few bytes */
-        ssize_t i = 0;
-        for (i = 0; i < bytes_read; i++) {
-            printf("%02x", (unsigned int)buf[i]);
-        }
-        printf("\n");
-    }
-    return CL_CLEAN; /* keep scanning */
-}
-
-/*
- * Exit codes:
- *  0: clean
- *  1: infected
- *  2: error
- */
-
-int main(int argc, char **argv)
-{
-    int status     = 2;
-    cl_error_t ret = CL_ERROR;
-
-    char *db_filepath = NULL;
-    int db_fd         = -1;
-    int target_fd     = -1;
-
-    unsigned long int size = 0;
-    long double mb;
-    const char *virname;
-    const char *filename;
-    struct cl_engine *engine = NULL;
-    struct cl_scan_options options;
-
-    if (argc != 2) {
-        printf("Usage: %s file\n", argv[0]);
-        return 2;
-    }
-
-    filename = argv[1];
-
-    if ((target_fd = open(argv[1], O_RDONLY)) == -1) {
-        printf("Can't open file %s\n", argv[1]);
-        goto done;
-    }
-
-    if (CL_SUCCESS != (ret = cl_init(CL_INIT_DEFAULT))) {
-        printf("Can't initialize libclamav: %s\n", cl_strerror(ret));
-        goto done;
-    }
-
-    if (!(engine = cl_engine_new())) {
-        printf("Can't create new engine\n");
-        goto done;
-    }
-
-    /* Example version macro usage to determine if new feature is available */
-#if defined(LIBCLAMAV_VERSION_NUM) && (LIBCLAMAV_VERSION_NUM >= 0x090400)
-    /* Example feature usage lowering max scan time to 15 seconds. */
-    cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, 15000);
-#endif
-    cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, 1024 /*MB*/ * 1024 /*KB*/ * 1024 /*bytes*/);
-    cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, 1024 /*MB*/ * 1024 /*KB*/ * 1024 /*bytes*/);
-
-    /* build engine */
-    if (CL_SUCCESS != (ret = cl_engine_compile(engine))) {
-        printf("Database initialization error: %s\n", cl_strerror(ret));
-        goto done;
-    }
-
-    /* scan file descriptor */
-    memset(&options, 0, sizeof(struct cl_scan_options));
-    options.parse |= ~0;                                 /* enable all parsers */
-    options.general |= CL_SCAN_GENERAL_HEURISTICS;       /* enable heuristic alert options */
-    options.general |= CL_SCAN_GENERAL_ALLMATCHES;       /* run in all-match mode, so it keeps looking for alerts after the first one */
-    options.general |= CL_SCAN_GENERAL_COLLECT_METADATA; /* collect metadata may enable collecting additional filenames (like in zip) */
-
-    /*
-     * Set our callbacks for inspecting embedded files during the scan.
-     */
-    cl_engine_set_clcb_pre_scan(engine, &scan_callback);
-
-    printf("Testing prescan on FD %d - %s\n", target_fd, filename);
-
-    if (CL_VIRUS == (ret = cl_scandesc(target_fd, filename, &virname, &size, engine, &options))) {
-        printf("Virus detected: %s\n", virname);
-    } else {
-        if (ret != CL_CLEAN) {
-            printf("Error: %s\n", cl_strerror(ret));
-            goto done;
-        }
-    }
-    /* calculate size of scanned data */
-    mb = size * (CL_COUNT_PRECISION / 1024) / 1024.0;
-    printf("Data scanned: %2.2Lf MB\n", mb);
-
-    status = ret == CL_VIRUS ? 1 : 0;
-
-done:
-
-    if (-1 != db_fd) {
-        close(db_fd);
-    }
-    if (-1 != target_fd) {
-        close(target_fd);
-    }
-    if (NULL != engine) {
-        cl_engine_free(engine);
-    }
-    if (NULL != db_filepath) {
-        free(db_filepath);
-    }
-
-    return status;
-}