blob: 1fe234aaeebf6973ae48414186aae5c18d76208b [file] [log] [blame]
#ifndef _TESTING_H
#define _TESTING_H
/* Testing code. */
#ifdef JUST_TESTING
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/utsname.h>
#include <asm/unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
/* We don't use all of these. */
static int modtest_uname(struct utsname *buf) __attribute__((unused));
static long modtest_create_module(const char *name, size_t size)
__attribute__((unused));
static void *modtest_fopen(const char *path, const char *mode)
__attribute__((unused));
static int modtest_open(const char *path, int flags, mode_t mode)
__attribute__((unused));
static int modtest_stat(const char *file_name, struct stat *buf)
__attribute__((unused));
static int modtest_lstat(const char *file_name, struct stat *buf)
__attribute__((unused));
static DIR *modtest_opendir(const char *name) __attribute__((unused));
static int modtest_system(const char *string) __attribute__((unused));
static int modtest_rename(const char *oldpath, const char *newpath)
__attribute__((unused));
static long modtest_init_module(void *map, unsigned long size,
const char *optstring) __attribute__((unused));
static long modtest_delete_module(const char *modname, unsigned int flags)
__attribute__((unused));
static int modtest_readlink(const char *path, char *buf, size_t bufsiz)
__attribute__((unused));
static int modtest_uname(struct utsname *buf)
{
char *release = NULL;
strcpy(buf->sysname, "Linux");
strcpy(buf->nodename, "fakenodename");
if ((release = getenv("MODTEST_UNAME")))
strcpy(buf->release, release);
else {
printf("MODTEST_OVERRIDE_ROOT used but MODTEST_UNAME not set.\n");
exit(1);
}
strcpy(buf->version, "Fakeversion");
strcpy(buf->machine, "fakemachine");
return 0;
}
static long modtest_create_module(const char *name, size_t size)
{
if (getenv("MODTEST_DO_CREATE_MODULE"))
return 0;
errno = ENOSYS;
return -1;
}
static const struct timespec modtest_delay = {
.tv_sec = 0,
.tv_nsec = 500 * 1000 * 1000
};
static long modtest_init_module(void *map, unsigned long size,
const char *optstring)
{
if (getenv("MODPROBE_WAIT")) {
int fd;
const char *file = getenv("MODPROBE_WAIT");
printf("Looping on %s\n", file);
fflush(stdout);
while ((fd = open(file, O_RDONLY)) < 0)
nanosleep(&modtest_delay, NULL);
close(fd);
printf("Removing %s\n", file);
unlink(file);
}
if (getenv("MODTEST_DUMP_INIT")) {
while (size) {
int ret;
ret = write(2, map, size);
if (ret < 0) exit(1);
size -= ret;
map += ret;
}
} else
printf("INIT_MODULE: %lu %s\n", size, optstring);
return 0;
}
static long modtest_delete_module(const char *modname, unsigned int flags)
{
char flagnames[100];
if (getenv("MODPROBE_WAIT")) {
int fd;
const char *file = getenv("MODPROBE_WAIT");
printf("Looping on %s\n", file);
fflush(stdout);
while ((fd = open(file, O_RDONLY)) < 0)
nanosleep(&modtest_delay, NULL);
close(fd);
printf("Removing %s\n", file);
fflush(stdout);
unlink(file);
}
flagnames[0] = '\0';
if (flags & O_EXCL)
strcat(flagnames, "EXCL ");
if (flags & O_TRUNC)
strcat(flagnames, "TRUNC ");
if (flags & O_NONBLOCK)
strcat(flagnames, "NONBLOCK ");
if (flags & ~(O_EXCL|O_TRUNC|O_NONBLOCK))
strcat(flagnames, "UNKNOWN ");
printf("DELETE_MODULE: %s %s\n", modname, flagnames);
return 0;
}
/* Add prefix to absolute paths; relative paths are left unchanged */
static const char *modtest_mapname(const char *path, char *buf, size_t buflen)
{
char *root;
if (path[0] != '/')
return path;
root = getenv("MODTEST_OVERRIDE_ROOT");
if (!root)
return path;
snprintf(buf, buflen, "%s%s", root, path);
return buf;
}
static void *modtest_fopen(const char *path, const char *mode)
{
char path_buf[PATH_MAX];
path = modtest_mapname(path, path_buf, sizeof(path_buf));
return fopen(path, mode);
}
static int modtest_open(const char *path, int flags, mode_t mode)
{
char path_buf[PATH_MAX];
path = modtest_mapname(path, path_buf, sizeof(path_buf));
return open(path, flags, mode);
}
static int modtest_stat(const char *path, struct stat *buf)
{
char path_buf[PATH_MAX];
path = modtest_mapname(path, path_buf, sizeof(path_buf));
return stat(path, buf);
}
static int modtest_lstat(const char *path, struct stat *buf)
{
char path_buf[PATH_MAX];
path = modtest_mapname(path, path_buf, sizeof(path_buf));
return lstat(path, buf);
}
static DIR *modtest_opendir(const char *path)
{
char path_buf[PATH_MAX];
path = modtest_mapname(path, path_buf, sizeof(path_buf));
return opendir(path);
}
static int modtest_system(const char *string)
{
if (getenv("MODTEST_DO_SYSTEM"))
return system(string);
printf("SYSTEM: %s\n", string);
return 0;
}
static int modtest_rename(const char *oldpath, const char *newpath)
{
char oldpath_buf[PATH_MAX];
char newpath_buf[PATH_MAX];
oldpath = modtest_mapname(oldpath, oldpath_buf, sizeof(oldpath_buf));
newpath = modtest_mapname(newpath, newpath_buf, sizeof(newpath_buf));
return rename(oldpath, newpath);
}
static int modtest_readlink(const char *path, char *buf, size_t bufsiz)
{
char path_buf[PATH_MAX];
path = modtest_mapname(path, path_buf, sizeof(path_buf));
return readlink(path, buf, bufsiz);
}
#ifdef CONFIG_USE_ZLIB
#include <zlib.h>
static gzFile *modtest_gzopen(const char *path, const char *mode)
__attribute__((unused));
static gzFile *modtest_gzopen(const char *path, const char *mode)
{
char path_buf[PATH_MAX];
path = modtest_mapname(path, path_buf, sizeof(path_buf));
return gzopen(path, mode);
}
#endif
/* create_module call */
#undef create_module
#define create_module modtest_create_module
#define uname modtest_uname
#define delete_module modtest_delete_module
#define init_module modtest_init_module
#define open modtest_open
#define fopen modtest_fopen
#define stat(name, ptr) modtest_stat(name, ptr)
#define lstat(name, ptr) modtest_lstat(name, ptr)
#define opendir modtest_opendir
#define system modtest_system
#define rename modtest_rename
#define readlink modtest_readlink
#define gzopen modtest_gzopen
#endif /* JUST_TESTING */
#endif /* _TESTING_H */