diff options
Diffstat (limited to '')
-rw-r--r-- | testsuite/delete_module.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/testsuite/delete_module.c b/testsuite/delete_module.c new file mode 100644 index 0000000..f3ae20b --- /dev/null +++ b/testsuite/delete_module.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2012-2013 ProFUSION embedded systems + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <dirent.h> +#include <dlfcn.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include <shared/util.h> + +#include "testsuite.h" + +struct mod { + struct mod *next; + int ret; + int errcode; + char name[]; +}; + +static struct mod *modules; +static bool need_init = true; + +static void parse_retcodes(struct mod **_modules, const char *s) +{ + const char *p; + + if (s == NULL) + return; + + for (p = s;;) { + struct mod *mod; + const char *modname; + char *end; + size_t modnamelen; + int ret, errcode; + long l; + + modname = p; + if (modname == NULL || modname[0] == '\0') + break; + + modnamelen = strcspn(p, ":"); + if (modname[modnamelen] != ':') + break; + + p = modname + modnamelen + 1; + if (p == NULL) + break; + + l = strtol(p, &end, 0); + if (end == p || *end != ':') + break; + + ret = (int) l; + p = end + 1; + + l = strtol(p, &end, 0); + if (*end == ':') + p = end + 1; + else if (*end != '\0') + break; + + errcode = (int) l; + + mod = malloc(sizeof(*mod) + modnamelen + 1); + if (mod == NULL) + break; + + memcpy(mod->name, modname, modnamelen); + mod->name[modnamelen] = '\0'; + mod->ret = ret; + mod->errcode = errcode; + mod->next = *_modules; + *_modules = mod; + } +} + +static struct mod *find_module(struct mod *_modules, const char *modname) +{ + struct mod *mod; + + for (mod = _modules; mod != NULL; mod = mod->next) { + if (streq(mod->name, modname)) + return mod; + } + + return NULL; +} + +static void init_retcodes(void) +{ + const char *s; + struct mod *mod; + + if (!need_init) + return; + + need_init = false; + s = getenv(S_TC_DELETE_MODULE_RETCODES); + if (s == NULL) { + ERR("TRAP delete_module(): missing export %s?\n", + S_TC_DELETE_MODULE_RETCODES); + } + + parse_retcodes(&modules, s); + + for (mod = modules; mod != NULL; mod = mod->next) { + LOG("Added module to test delete_module:\n"); + LOG("\tname=%s ret=%d errcode=%d\n", + mod->name, mod->ret, mod->errcode); + } +} + +TS_EXPORT long delete_module(const char *name, unsigned int flags); + +/* + * FIXME: change /sys/module/<modname> to fake-remove a module + * + * Default behavior is to exit successfully. If this is not the intended + * behavior, set TESTSUITE_DELETE_MODULE_RETCODES env var. + */ +long delete_module(const char *modname, unsigned int flags) +{ + struct mod *mod; + + init_retcodes(); + mod = find_module(modules, modname); + if (mod == NULL) + return 0; + + errno = mod->errcode; + return mod->ret; +} + +/* the test is going away anyway, but lets keep valgrind happy */ +void free_resources(void) __attribute__((destructor)); +void free_resources(void) +{ + while (modules) { + struct mod *mod = modules->next; + free(modules); + modules = mod; + } +} |