xref: /aosp_15_r20/external/kmod/testsuite/delete_module.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2012-2013  ProFUSION embedded systems
3*cc4ad7daSAndroid Build Coastguard Worker  *
4*cc4ad7daSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
5*cc4ad7daSAndroid Build Coastguard Worker  * modify it under the terms of the GNU Lesser General Public
6*cc4ad7daSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation; either
7*cc4ad7daSAndroid Build Coastguard Worker  * version 2.1 of the License, or (at your option) any later version.
8*cc4ad7daSAndroid Build Coastguard Worker  *
9*cc4ad7daSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
10*cc4ad7daSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*cc4ad7daSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*cc4ad7daSAndroid Build Coastguard Worker  * Lesser General Public License for more details.
13*cc4ad7daSAndroid Build Coastguard Worker  *
14*cc4ad7daSAndroid Build Coastguard Worker  * You should have received a copy of the GNU Lesser General Public
15*cc4ad7daSAndroid Build Coastguard Worker  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16*cc4ad7daSAndroid Build Coastguard Worker  */
17*cc4ad7daSAndroid Build Coastguard Worker 
18*cc4ad7daSAndroid Build Coastguard Worker #include <assert.h>
19*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
20*cc4ad7daSAndroid Build Coastguard Worker #include <dlfcn.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <fcntl.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <stddef.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <sys/types.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
32*cc4ad7daSAndroid Build Coastguard Worker 
33*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
34*cc4ad7daSAndroid Build Coastguard Worker 
35*cc4ad7daSAndroid Build Coastguard Worker #include "testsuite.h"
36*cc4ad7daSAndroid Build Coastguard Worker 
37*cc4ad7daSAndroid Build Coastguard Worker struct mod {
38*cc4ad7daSAndroid Build Coastguard Worker 	struct mod *next;
39*cc4ad7daSAndroid Build Coastguard Worker 	int ret;
40*cc4ad7daSAndroid Build Coastguard Worker 	int errcode;
41*cc4ad7daSAndroid Build Coastguard Worker 	char name[];
42*cc4ad7daSAndroid Build Coastguard Worker };
43*cc4ad7daSAndroid Build Coastguard Worker 
44*cc4ad7daSAndroid Build Coastguard Worker static struct mod *modules;
45*cc4ad7daSAndroid Build Coastguard Worker static bool need_init = true;
46*cc4ad7daSAndroid Build Coastguard Worker 
parse_retcodes(struct mod ** _modules,const char * s)47*cc4ad7daSAndroid Build Coastguard Worker static void parse_retcodes(struct mod **_modules, const char *s)
48*cc4ad7daSAndroid Build Coastguard Worker {
49*cc4ad7daSAndroid Build Coastguard Worker 	const char *p;
50*cc4ad7daSAndroid Build Coastguard Worker 
51*cc4ad7daSAndroid Build Coastguard Worker 	if (s == NULL)
52*cc4ad7daSAndroid Build Coastguard Worker 		return;
53*cc4ad7daSAndroid Build Coastguard Worker 
54*cc4ad7daSAndroid Build Coastguard Worker 	for (p = s;;) {
55*cc4ad7daSAndroid Build Coastguard Worker 		struct mod *mod;
56*cc4ad7daSAndroid Build Coastguard Worker 		const char *modname;
57*cc4ad7daSAndroid Build Coastguard Worker 		char *end;
58*cc4ad7daSAndroid Build Coastguard Worker 		size_t modnamelen;
59*cc4ad7daSAndroid Build Coastguard Worker 		int ret, errcode;
60*cc4ad7daSAndroid Build Coastguard Worker 		long l;
61*cc4ad7daSAndroid Build Coastguard Worker 
62*cc4ad7daSAndroid Build Coastguard Worker 		modname = p;
63*cc4ad7daSAndroid Build Coastguard Worker 		if (modname == NULL || modname[0] == '\0')
64*cc4ad7daSAndroid Build Coastguard Worker 			break;
65*cc4ad7daSAndroid Build Coastguard Worker 
66*cc4ad7daSAndroid Build Coastguard Worker 		modnamelen = strcspn(p, ":");
67*cc4ad7daSAndroid Build Coastguard Worker 		if (modname[modnamelen] != ':')
68*cc4ad7daSAndroid Build Coastguard Worker 			break;
69*cc4ad7daSAndroid Build Coastguard Worker 
70*cc4ad7daSAndroid Build Coastguard Worker 		p = modname + modnamelen + 1;
71*cc4ad7daSAndroid Build Coastguard Worker 		if (p == NULL)
72*cc4ad7daSAndroid Build Coastguard Worker 			break;
73*cc4ad7daSAndroid Build Coastguard Worker 
74*cc4ad7daSAndroid Build Coastguard Worker 		l = strtol(p, &end, 0);
75*cc4ad7daSAndroid Build Coastguard Worker 		if (end == p || *end != ':')
76*cc4ad7daSAndroid Build Coastguard Worker 			break;
77*cc4ad7daSAndroid Build Coastguard Worker 
78*cc4ad7daSAndroid Build Coastguard Worker 		ret = (int) l;
79*cc4ad7daSAndroid Build Coastguard Worker 		p = end + 1;
80*cc4ad7daSAndroid Build Coastguard Worker 
81*cc4ad7daSAndroid Build Coastguard Worker 		l = strtol(p, &end, 0);
82*cc4ad7daSAndroid Build Coastguard Worker 		if (*end == ':')
83*cc4ad7daSAndroid Build Coastguard Worker 			p = end + 1;
84*cc4ad7daSAndroid Build Coastguard Worker 		else if (*end != '\0')
85*cc4ad7daSAndroid Build Coastguard Worker 			break;
86*cc4ad7daSAndroid Build Coastguard Worker 
87*cc4ad7daSAndroid Build Coastguard Worker 		errcode = (int) l;
88*cc4ad7daSAndroid Build Coastguard Worker 
89*cc4ad7daSAndroid Build Coastguard Worker 		mod = malloc(sizeof(*mod) + modnamelen + 1);
90*cc4ad7daSAndroid Build Coastguard Worker 		if (mod == NULL)
91*cc4ad7daSAndroid Build Coastguard Worker 			break;
92*cc4ad7daSAndroid Build Coastguard Worker 
93*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(mod->name, modname, modnamelen);
94*cc4ad7daSAndroid Build Coastguard Worker 		mod->name[modnamelen] = '\0';
95*cc4ad7daSAndroid Build Coastguard Worker 		mod->ret = ret;
96*cc4ad7daSAndroid Build Coastguard Worker 		mod->errcode = errcode;
97*cc4ad7daSAndroid Build Coastguard Worker 		mod->next = *_modules;
98*cc4ad7daSAndroid Build Coastguard Worker 		*_modules = mod;
99*cc4ad7daSAndroid Build Coastguard Worker 	}
100*cc4ad7daSAndroid Build Coastguard Worker }
101*cc4ad7daSAndroid Build Coastguard Worker 
find_module(struct mod * _modules,const char * modname)102*cc4ad7daSAndroid Build Coastguard Worker static struct mod *find_module(struct mod *_modules, const char *modname)
103*cc4ad7daSAndroid Build Coastguard Worker {
104*cc4ad7daSAndroid Build Coastguard Worker 	struct mod *mod;
105*cc4ad7daSAndroid Build Coastguard Worker 
106*cc4ad7daSAndroid Build Coastguard Worker 	for (mod = _modules; mod != NULL; mod = mod->next) {
107*cc4ad7daSAndroid Build Coastguard Worker 		if (streq(mod->name, modname))
108*cc4ad7daSAndroid Build Coastguard Worker 			return mod;
109*cc4ad7daSAndroid Build Coastguard Worker 	}
110*cc4ad7daSAndroid Build Coastguard Worker 
111*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
112*cc4ad7daSAndroid Build Coastguard Worker }
113*cc4ad7daSAndroid Build Coastguard Worker 
init_retcodes(void)114*cc4ad7daSAndroid Build Coastguard Worker static void init_retcodes(void)
115*cc4ad7daSAndroid Build Coastguard Worker {
116*cc4ad7daSAndroid Build Coastguard Worker 	const char *s;
117*cc4ad7daSAndroid Build Coastguard Worker 	struct mod *mod;
118*cc4ad7daSAndroid Build Coastguard Worker 
119*cc4ad7daSAndroid Build Coastguard Worker 	if (!need_init)
120*cc4ad7daSAndroid Build Coastguard Worker 		return;
121*cc4ad7daSAndroid Build Coastguard Worker 
122*cc4ad7daSAndroid Build Coastguard Worker 	need_init = false;
123*cc4ad7daSAndroid Build Coastguard Worker 	s = getenv(S_TC_DELETE_MODULE_RETCODES);
124*cc4ad7daSAndroid Build Coastguard Worker 	if (s == NULL) {
125*cc4ad7daSAndroid Build Coastguard Worker 		ERR("TRAP delete_module(): missing export %s?\n",
126*cc4ad7daSAndroid Build Coastguard Worker 						S_TC_DELETE_MODULE_RETCODES);
127*cc4ad7daSAndroid Build Coastguard Worker 	}
128*cc4ad7daSAndroid Build Coastguard Worker 
129*cc4ad7daSAndroid Build Coastguard Worker 	parse_retcodes(&modules, s);
130*cc4ad7daSAndroid Build Coastguard Worker 
131*cc4ad7daSAndroid Build Coastguard Worker 	for (mod = modules; mod != NULL; mod = mod->next) {
132*cc4ad7daSAndroid Build Coastguard Worker 		LOG("Added module to test delete_module:\n");
133*cc4ad7daSAndroid Build Coastguard Worker 		LOG("\tname=%s ret=%d errcode=%d\n",
134*cc4ad7daSAndroid Build Coastguard Worker 		    mod->name, mod->ret, mod->errcode);
135*cc4ad7daSAndroid Build Coastguard Worker 	}
136*cc4ad7daSAndroid Build Coastguard Worker }
137*cc4ad7daSAndroid Build Coastguard Worker 
138*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT long delete_module(const char *name, unsigned int flags);
139*cc4ad7daSAndroid Build Coastguard Worker 
140*cc4ad7daSAndroid Build Coastguard Worker /*
141*cc4ad7daSAndroid Build Coastguard Worker  * FIXME: change /sys/module/<modname> to fake-remove a module
142*cc4ad7daSAndroid Build Coastguard Worker  *
143*cc4ad7daSAndroid Build Coastguard Worker  * Default behavior is to exit successfully. If this is not the intended
144*cc4ad7daSAndroid Build Coastguard Worker  * behavior, set TESTSUITE_DELETE_MODULE_RETCODES env var.
145*cc4ad7daSAndroid Build Coastguard Worker  */
delete_module(const char * modname,unsigned int flags)146*cc4ad7daSAndroid Build Coastguard Worker long delete_module(const char *modname, unsigned int flags)
147*cc4ad7daSAndroid Build Coastguard Worker {
148*cc4ad7daSAndroid Build Coastguard Worker 	struct mod *mod;
149*cc4ad7daSAndroid Build Coastguard Worker 
150*cc4ad7daSAndroid Build Coastguard Worker 	init_retcodes();
151*cc4ad7daSAndroid Build Coastguard Worker 	mod = find_module(modules, modname);
152*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
153*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
154*cc4ad7daSAndroid Build Coastguard Worker 
155*cc4ad7daSAndroid Build Coastguard Worker 	errno = mod->errcode;
156*cc4ad7daSAndroid Build Coastguard Worker 	return mod->ret;
157*cc4ad7daSAndroid Build Coastguard Worker }
158*cc4ad7daSAndroid Build Coastguard Worker 
159*cc4ad7daSAndroid Build Coastguard Worker /* the test is going away anyway, but lets keep valgrind happy */
160*cc4ad7daSAndroid Build Coastguard Worker void free_resources(void) __attribute__((destructor));
free_resources(void)161*cc4ad7daSAndroid Build Coastguard Worker void free_resources(void)
162*cc4ad7daSAndroid Build Coastguard Worker {
163*cc4ad7daSAndroid Build Coastguard Worker 	while (modules) {
164*cc4ad7daSAndroid Build Coastguard Worker 		struct mod *mod = modules->next;
165*cc4ad7daSAndroid Build Coastguard Worker 		free(modules);
166*cc4ad7daSAndroid Build Coastguard Worker 		modules = mod;
167*cc4ad7daSAndroid Build Coastguard Worker 	}
168*cc4ad7daSAndroid Build Coastguard Worker }
169