Customizing I/O of CoverageScanner library

Custom I/O using C file access

The following example shows how to generate the execution report using the standard C file API.

To compile the example on Microsoft® Windows:

cscl customiofile.c

To compile the example on Linux™ or macOS:

csgcc customiofile.c -o customiofile

Source code:

#include <stdio.h>
#include <string.h>
#define VERBOSE 1

static int csfputs(const char *s, void *stream) {
#if VERBOSE
    fprintf(stderr, "csfputs:%s\n", s);
#endif
    return fputs(s, (FILE *)stream);
}

static void *csfopenappend(const char *path) {
#if VERBOSE
    fprintf(stderr, "csfopenappend:%s\n", path);
#endif
    return (void *)fopen(path, "a+");
}

static void *csfopenread(const char *path) {
#if VERBOSE
    fprintf(stderr, "csfopenread:%s\n", path);
#endif
    return (void *)fopen(path, "r");
}

static void *csfopenwrite(const char *path) {
#if VERBOSE
    fprintf(stderr, "csfopenwrite:%s\n", path);
#endif
    return (void *)fopen(path, "w");
}

static char *csfgets(char *s, int size, void *stream) {
    char *ret;
    ret = fgets(s, size, (FILE *)stream);
#if VERBOSE
    fprintf(stderr, "csfgets:%s\n", s);
#endif
    return ret;
}

static int csremove(const char *path) {
#if VERBOSE
    fprintf(stderr, "csremove:%s\n", path);
#endif
    return remove(path);
}

static int csfclose(void *stream) {
#if VERBOSE
    fprintf(stderr, "csfclose\n");
#endif
    return fclose((FILE *)stream);
}

int main(int argc, char* argv[]) {
    char location[256];
    int lg_location;

    printf(".csexe file name (without extension}:");
    fflush(stdout);
    fgets(location, sizeof(location), stdin);
    lg_location = strlen(location);
    if (lg_location)
        location[lg_location - 1] = '\0'; // strip \n
#ifdef __COVERAGESCANNER__
    __coveragescanner_set_custom_io(csfgets, csfputs, csfopenappend,
                                    csfopenread, csfopenwrite, csfclose,
                                    csremove);
    __coveragescanner_install(location);
#endif
}

Custom I/O using SFTP protocol

The following example shows how to generate the execution report directly on a SFTP server. The SFTP server is part of SSH v2 and is available on most Unix platforms. On Windows, a free SSH server can be downloaded from freeSSHd and freeFTPd.

To compile the example on Windows:

  1. Download libSSH2 from libssh2. Build the library, and set the environment variable LIBSSH2 to the build/install location
  2. To compile the example:
    cscl %LIBSSH2%\win32\debug_dll\libssh2.lib -DWIN32 --cs-libgen=/MTd
         /MTd -I %LIBSSH2%\include ws2_32.lib customiosftp.c
  3. Execute custom_io_sftp.exe.

To compile the example on Linux™:

  1. Install the development package of libssh2.
  2. To compile the example:
    csgcc -lssh2 customiosftp.c -o customiosftp
  3. Execute custom_io_sftp.

Source code:

#define VERBOSE 1

#ifdef WIN32
#include <winsock2.h>
#define LIBSSH2_WIN32
#define LIBSSH2_API
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#include <libssh2.h>
#include <libssh2_sftp.h>

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>

static LIBSSH2_SESSION *session = NULL;
static LIBSSH2_SFTP *sftp_session = NULL;
static int sock = 0;

static void extract_location(const char *location, char *server, char *user,
                             char *passwd, char *file) {
    int i, j;
    int lg_location;
    lg_location = strlen(location);
    for (i = 0; i < lg_location; i++) {
        if (location[i] == '\n')
            break;
        server[i] = location[i];
    }
    server[i] = '\0';
    i++;

    for (j = 0; i < lg_location; i++, j++) {
        if (location[i] == '\n')
            break;
        user[j] = location[i];
    }
    user[j] = '\0';
    i++;

    for (j = 0; i < lg_location; i++, j++) {
        if (location[i] == '\n')
            break;
        passwd[j] = location[i];
    }
    passwd[j] = '\0';
    i++;

    for (j = 0; i < lg_location; i++, j++) {
        if (location[i] == '\0')
            break;
        file[j] = location[i];
    }
    file[j] = '\0';
}

static void close_sftp_session() {
    if (sftp_session)
        libssh2_sftp_shutdown(sftp_session);
    sftp_session = NULL;

    if (session) {
        libssh2_session_disconnect(session,
                                   "Normal Shutdown, Thank you for playing");
        libssh2_session_free(session);
    }
    session = NULL;

    if (sock) {
#ifdef WIN32
        Sleep(1000);
        closesocket(sock);
#else
        sleep(1);
        close(sock);
#endif
    }
    sock = 0;
}

static int open_sftp_session(const char *server, const char *user,
                             const char *passwd) {
    struct sockaddr_in sin;
    int rc;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    sin.sin_family = AF_INET;
    sin.sin_port = htons(22);
    sin.sin_addr.s_addr = inet_addr(server);
    if (connect(sock, (struct sockaddr *)(&sin), sizeof(struct sockaddr_in)) !=
        0) {
        close_sftp_session();
        return 0;
    }

    /* Create a session instance
     */
    session = libssh2_session_init();
    if (!session) {
        close_sftp_session();
        return 0;
    }

    /* ... start it up. This will trade welcome banners, exchange keys,
     * and setup crypto, compression, and MAC layers
     */
    rc = libssh2_session_startup(session, sock);
    if (rc) {
        close_sftp_session();
        return 0;
    }

    libssh2_session_set_blocking(session, 1);

    if (libssh2_userauth_password(session, user, passwd)) {
        close_sftp_session();
        return 0;
    }

    sftp_session = libssh2_sftp_init(session);

    if (!sftp_session) {
        close_sftp_session();
        return 0;
    }
    return 1;
}

static int csfputs(const char *s, void *stream) {
#if VERBOSE
    fprintf(stderr, "csfputs:%s\n", s);
#endif
    return libssh2_sftp_write((LIBSSH2_SFTP_HANDLE *)stream, s, strlen(s));
}

static void *csfopenappend(const char *location) {
    LIBSSH2_SFTP_HANDLE *handle;
    char server[1024];
    char user[1024];
    char passwd[1024];
    char file[1024];
    LIBSSH2_SFTP_ATTRIBUTES attrs;

    extract_location(location, server, user, passwd, file);
#if VERBOSE
    fprintf(stderr, "csfopenappend %s:%s:%s\n", server, user, file);
#endif
    if (open_sftp_session(server, user, passwd)) {
        handle = libssh2_sftp_open(
            sftp_session, file, LIBSSH2_FXF_CREAT | LIBSSH2_FXF_WRITE,
            LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP |
                LIBSSH2_SFTP_S_IROTH);
    } else
        return NULL;

    if (handle) {
        if (libssh2_sftp_fstat(handle, &attrs) ==
            0) { /* Go to the end of the file */
            libssh2_sftp_seek(handle, attrs.filesize);
        }
    }
    return handle;
}

static void *csfopenread(const char *location) {
    char server[1024];
    char user[1024];
    char passwd[1024];
    char file[1024];

    extract_location(location, server, user, passwd, file);
#if VERBOSE
    fprintf(stderr, "csfopenread %s:%s:%s\n", server, user, file);
#endif
    if (open_sftp_session(server, user, passwd))
        return (void *)libssh2_sftp_open(sftp_session, file, LIBSSH2_FXF_READ,
                                         0);
    else
        return NULL;
}

static void *csfopenwrite(const char *location) {
    char server[1024];
    char user[1024];
    char passwd[1024];
    char file[1024];

    extract_location(location, server, user, passwd, file);
#if VERBOSE
    fprintf(stderr, "csfopenwrite %s:%s:%s\n", server, user, file);
#endif
    if (open_sftp_session(server, user, passwd))
        return (void *)libssh2_sftp_open(
            sftp_session, file, LIBSSH2_FXF_CREAT | LIBSSH2_FXF_WRITE,
            LIBSSH2_SFTP_S_IRUSR | LIBSSH2_SFTP_S_IWUSR | LIBSSH2_SFTP_S_IRGRP |
                LIBSSH2_SFTP_S_IROTH);
    else
        return NULL;
}

static char *csfgets(char *s, int size, void *stream) {
    size_t ss;
    ss = libssh2_sftp_read((LIBSSH2_SFTP_HANDLE *)stream, s, size - 1);
    if (ss) {
        s[ss] = '\0';
#if VERBOSE
        fprintf(stderr, "csfgets:%s\n", s);
#endif
        return s;
    } else
        return NULL;
}

static int csremove(const char *location) {
    int ret;
    char server[1024];
    char user[1024];
    char passwd[1024];
    char file[1024];

    extract_location(location, server, user, passwd, file);
#if VERBOSE
    fprintf(stderr, "csremove %s:%s:%s\n", server, user, file);
#endif
    if (open_sftp_session(server, user, passwd)) {
        ret = libssh2_sftp_unlink(sftp_session, file);
        close_sftp_session();
        return ret;
    } else
        return -1;
}

static int csfclose(void *fp) {
#if VERBOSE
    fprintf(stderr, "csfclose\n");
#endif
    return libssh2_sftp_close((LIBSSH2_SFTP_HANDLE *)fp);
}

int main() {
    char location[1024];
    char tmp[1024];
#ifdef WIN32
    WSADATA wsadata;

    WSAStartup(WINSOCK_VERSION, &wsadata);
#endif

    location[0] = '\0';

    printf("server IP:");
    fflush(stdout);
    fgets(tmp, sizeof(tmp), stdin);
    strcat(location, tmp);

    printf("user:");
    fflush(stdout);
    fgets(tmp, sizeof(tmp), stdin);
    strcat(location, tmp);

    printf("passwd:");
    fflush(stdout);
    fgets(tmp, sizeof(tmp), stdin);
    strcat(location, tmp);

    printf(".csexe file name (without extension}:");
    fflush(stdout);
    fgets(tmp, sizeof(tmp), stdin);
    strcat(location, tmp);

    location[strlen(location) - 1] = '\0';

#ifdef __COVERAGESCANNER__
    __coveragescanner_set_custom_io(csfgets, csfputs, csfopenappend,
                                    csfopenread, csfopenwrite, csfclose,
                                    csremove);
    __coveragescanner_install(location);
#endif
}

Coco v7.2.0 ©2024 The Qt Company Ltd.
Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.