xref: /aosp_15_r20/external/kmod/testsuite/path.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
1 /*
2  * Copyright (C) 2012-2013  ProFUSION embedded systems
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /* We unset _FILE_OFFSET_BITS here so we can override both stat and stat64 on
19  * 32-bit architectures and forward each to the right libc function */
20 #undef _FILE_OFFSET_BITS
21 
22 #include <assert.h>
23 #include <dirent.h>
24 #include <dlfcn.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <limits.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 
36 #include <shared/util.h>
37 
38 #include "testsuite.h"
39 
40 static void *nextlib;
41 static const char *rootpath;
42 static size_t rootpathlen;
43 
need_trap(const char * path)44 static inline bool need_trap(const char *path)
45 {
46 	return path != NULL && path[0] == '/'
47 		&& !strstartswith(path, ABS_TOP_BUILDDIR);
48 }
49 
trap_path(const char * path,char buf[PATH_MAX * 2])50 static const char *trap_path(const char *path, char buf[PATH_MAX * 2])
51 {
52 	size_t len;
53 
54 	if (!need_trap(path))
55 		return path;
56 
57 	len = strlen(path);
58 
59 	if (len + rootpathlen > PATH_MAX * 2) {
60 		errno = ENAMETOOLONG;
61 		return NULL;
62 	}
63 
64 	memcpy(buf, rootpath, rootpathlen);
65 	strcpy(buf + rootpathlen, path);
66 	return buf;
67 }
68 
get_rootpath(const char * f)69 static bool get_rootpath(const char *f)
70 {
71 	if (rootpath != NULL)
72 		return true;
73 
74 	rootpath = getenv(S_TC_ROOTFS);
75 	if (rootpath == NULL) {
76 		ERR("TRAP %s(): missing export %s?\n", f, S_TC_ROOTFS);
77 		errno = ENOENT;
78 		return false;
79 	}
80 
81 	rootpathlen = strlen(rootpath);
82 
83 	return true;
84 }
85 
get_libc_func(const char * f)86 static void *get_libc_func(const char *f)
87 {
88 	void *fp;
89 
90 	if (nextlib == NULL) {
91 #ifdef RTLD_NEXT
92 		nextlib = RTLD_NEXT;
93 #else
94 		nextlib = dlopen("libc.so.6", RTLD_LAZY);
95 #endif
96 	}
97 
98 	fp = dlsym(nextlib, f);
99 	assert(fp);
100 
101 	return fp;
102 }
103 
104 /* wrapper template for a function with one "const char* path" argument */
105 #define WRAP_1ARG(rettype, failret, name) \
106 TS_EXPORT rettype name(const char *path) \
107 { \
108 	const char *p;				\
109 	char buf[PATH_MAX * 2];                 \
110 	static rettype (*_fn)(const char*);	\
111 						\
112 	if (!get_rootpath(__func__))		\
113 		return failret;			\
114 	_fn = get_libc_func(#name);		\
115 	p = trap_path(path, buf);		\
116 	if (p == NULL)				\
117 		return failret;			\
118 	return (*_fn)(p);			\
119 }
120 
121 /* wrapper template for a function with "const char* path" and another argument */
122 #define WRAP_2ARGS(rettype, failret, name, arg2t)	\
123 TS_EXPORT rettype name(const char *path, arg2t arg2)	\
124 { \
125 	const char *p;					\
126 	char buf[PATH_MAX * 2];				\
127 	static rettype (*_fn)(const char*, arg2t arg2);	\
128 							\
129 	if (!get_rootpath(__func__))			\
130 		return failret;				\
131 	_fn = get_libc_func(#name);			\
132 	p = trap_path(path, buf);			\
133 	if (p == NULL)					\
134 		return failret;				\
135 	return (*_fn)(p, arg2);				\
136 }
137 
138 /* wrapper template for open family */
139 #define WRAP_OPEN(suffix)					\
140 TS_EXPORT int open ## suffix (const char *path, int flags, ...)	\
141 { \
142 	const char *p;						\
143 	char buf[PATH_MAX * 2];					\
144 	static int (*_fn)(const char *path, int flags, ...);	\
145 								\
146 	if (!get_rootpath(__func__))				\
147 		return -1;					\
148 	_fn = get_libc_func("open" #suffix);			\
149 	p = trap_path(path, buf);				\
150 	if (p == NULL)						\
151 		return -1;					\
152 								\
153 	if (flags & O_CREAT) {					\
154 		mode_t mode;					\
155 		va_list ap;					\
156 								\
157 		va_start(ap, flags);				\
158 		mode = va_arg(ap, mode_t);			\
159 		va_end(ap);					\
160 		return _fn(p, flags, mode);			\
161 	}							\
162 								\
163 	return _fn(p, flags);					\
164 }
165 
166 /*
167  * wrapper template for __xstat family
168  * This family got deprecated/dropped in glibc 2.32.9000, but we still need
169  * to keep it for a while for programs that were built against previous versions
170  */
171 #define WRAP_VERSTAT(prefix, suffix)			    \
172 TS_EXPORT int prefix ## stat ## suffix (int ver,	    \
173 			      const char *path,		    \
174 	                      struct stat ## suffix *st);   \
175 TS_EXPORT int prefix ## stat ## suffix (int ver,	    \
176 			      const char *path,		    \
177 	                      struct stat ## suffix *st)    \
178 { \
179 	const char *p;					    \
180 	char buf[PATH_MAX * 2];				    \
181 	static int (*_fn)(int ver, const char *path,	    \
182 		          struct stat ## suffix *);	    \
183 	_fn = get_libc_func(#prefix "stat" #suffix);	    \
184 							    \
185 	if (!get_rootpath(__func__))			    \
186 		return -1;				    \
187 	p = trap_path(path, buf);			    \
188 	if (p == NULL)					    \
189 		return -1;				    \
190 							    \
191 	return _fn(ver, p, st);				    \
192 }
193 
194 WRAP_1ARG(DIR*, NULL, opendir);
195 WRAP_1ARG(int, -1, chdir);
196 
197 WRAP_2ARGS(FILE*, NULL, fopen, const char*);
198 WRAP_2ARGS(FILE*, NULL, fopen64, const char*);
199 WRAP_2ARGS(int, -1, mkdir, mode_t);
200 WRAP_2ARGS(int, -1, access, int);
201 WRAP_2ARGS(int, -1, stat, struct stat*);
202 WRAP_2ARGS(int, -1, lstat, struct stat*);
203 WRAP_2ARGS(int, -1, stat64, struct stat64*);
204 WRAP_2ARGS(int, -1, lstat64, struct stat64*);
205 WRAP_OPEN(64);
206 
207 WRAP_OPEN();
208 
209 #ifdef HAVE___XSTAT
210 WRAP_VERSTAT(__x,);
211 WRAP_VERSTAT(__lx,);
212 WRAP_VERSTAT(__x,64);
213 WRAP_VERSTAT(__lx,64);
214 #endif
215