]> git.ipfire.org Git - thirdparty/kmod.git/blob - testsuite/path.c
Check if libc has __xstat
[thirdparty/kmod.git] / testsuite / path.c
1 /*
2 * Copyright (C) 2012 ProFUSION embedded systems
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <assert.h>
19 #include <errno.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <dlfcn.h>
23 #include <limits.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 #include "testsuite.h"
33
34 static void *nextlib;
35 static const char *rootpath;
36 static size_t rootpathlen;
37
38 static inline bool need_trap(const char *path)
39 {
40 return path != NULL && path[0] == '/';
41 }
42
43 static const char *trap_path(const char *path, char buf[PATH_MAX * 2])
44 {
45 size_t len;
46
47 if (!need_trap(path))
48 return path;
49
50 len = strlen(path);
51
52 if (len + rootpathlen > PATH_MAX * 2) {
53 errno = ENAMETOOLONG;
54 return NULL;
55 }
56
57 memcpy(buf, rootpath, rootpathlen);
58 strcpy(buf + rootpathlen, path);
59 return buf;
60 }
61
62 static bool get_rootpath(const char *f)
63 {
64 if (rootpath != NULL)
65 return true;
66
67 rootpath = getenv(S_TC_ROOTFS);
68 if (rootpath == NULL) {
69 ERR("TRAP %s(): missing export %s?\n", f, S_TC_ROOTFS);
70 errno = ENOENT;
71 return false;
72 }
73
74 rootpathlen = strlen(rootpath);
75
76 return true;
77 }
78
79 static void *get_libc_func(const char *f)
80 {
81 void *fp;
82
83 if (nextlib == NULL) {
84 #ifdef RTLD_NEXT
85 nextlib = RTLD_NEXT;
86 #else
87 nextlib = dlopen("libc.so.6", RTLD_LAZY);
88 #endif
89 }
90
91 fp = dlsym(nextlib, f);
92 assert(fp);
93
94 return fp;
95 }
96
97 TS_EXPORT FILE *fopen(const char *path, const char *mode)
98 {
99 const char *p;
100 char buf[PATH_MAX * 2];
101 static int (*_fopen)(const char *path, const char *mode);
102
103 if (!get_rootpath(__func__))
104 return NULL;
105
106 _fopen = get_libc_func("fopen");
107
108 p = trap_path(path, buf);
109 if (p == NULL)
110 return NULL;
111
112 return (void *) (long) (*_fopen)(p, mode);
113 }
114
115 TS_EXPORT int open(const char *path, int flags, ...)
116 {
117 const char *p;
118 char buf[PATH_MAX * 2];
119 static int (*_open)(const char *path, int flags, ...);
120
121 if (!get_rootpath(__func__))
122 return -1;
123
124 _open = get_libc_func("open");
125 p = trap_path(path, buf);
126 if (p == NULL)
127 return -1;
128
129 if (flags & O_CREAT) {
130 mode_t mode;
131 va_list ap;
132
133 va_start(ap, flags);
134 mode = va_arg(ap, mode_t);
135 va_end(ap);
136 _open(p, flags, mode);
137 }
138
139 return _open(p, flags);
140 }
141
142 TS_EXPORT int stat(const char *path, struct stat *st)
143 {
144 const char *p;
145 char buf[PATH_MAX * 2];
146 static int (*_stat)(const char *path, struct stat *buf);
147
148 if (!get_rootpath(__func__))
149 return -1;
150
151 _stat = get_libc_func("stat");
152
153 p = trap_path(path, buf);
154 if (p == NULL)
155 return -1;
156
157 return _stat(p, st);
158 }
159
160 #ifdef HAVE___XSTAT
161 TS_EXPORT int __xstat(int ver, const char *path, struct stat *st)
162 {
163 const char *p;
164 char buf[PATH_MAX * 2];
165 static int (*_xstat)(int __ver, const char *__filename,
166 struct stat *__stat_buf);
167
168 if (!get_rootpath(__func__))
169 return -1;
170
171 _xstat = get_libc_func("__xstat");
172
173 p = trap_path(path, buf);
174 if (p == NULL)
175 return -1;
176
177 return _xstat(ver, p, st);
178 }
179 #endif
180
181 TS_EXPORT int access(const char *path, int mode)
182 {
183 const char *p;
184 char buf[PATH_MAX * 2];
185 static int (*_access)(const char *path, int mode);
186
187 if (!get_rootpath(__func__))
188 return -1;
189
190 _access = get_libc_func("access");
191
192 p = trap_path(path, buf);
193 if (p == NULL)
194 return -1;
195
196 return _access(p, mode);
197 }
198
199 TS_EXPORT DIR *opendir(const char *path)
200 {
201 const char *p;
202 char buf[PATH_MAX * 2];
203 static int (*_opendir)(const char *path);
204
205 if (!get_rootpath(__func__))
206 return NULL;
207
208 _opendir = get_libc_func("opendir");
209
210 p = trap_path(path, buf);
211 if (p == NULL)
212 return NULL;
213
214 return (void *)(long)(*_opendir)(p);
215 }