]> git.ipfire.org Git - thirdparty/kmod.git/blame - testsuite/path.c
testsuite preload: Factorize into macros, add more stat and open variants
[thirdparty/kmod.git] / testsuite / path.c
CommitLineData
e701e381
LDM
1/*
2 * Copyright (C) 2012 ProFUSION embedded systems
3 *
e1b1ab24
LDM
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.
e701e381
LDM
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
e1b1ab24
LDM
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
e701e381 13 *
e1b1ab24
LDM
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
e701e381
LDM
17 */
18
6afc9cd6
LDM
19#include <assert.h>
20#include <errno.h>
4e36cb18 21#include <dirent.h>
7fa8c2d2 22#include <fcntl.h>
6afc9cd6
LDM
23#include <dlfcn.h>
24#include <limits.h>
25#include <stdlib.h>
7fa8c2d2 26#include <stdarg.h>
6afc9cd6
LDM
27#include <string.h>
28#include <stdio.h>
7fa8c2d2
LDM
29#include <sys/types.h>
30#include <sys/stat.h>
1426a613 31#include <unistd.h>
6afc9cd6
LDM
32
33#include "testsuite.h"
34
35static void *nextlib;
36static const char *rootpath;
37static size_t rootpathlen;
38
39static inline bool need_trap(const char *path)
40{
41 return path != NULL && path[0] == '/';
42}
43
44static const char *trap_path(const char *path, char buf[PATH_MAX * 2])
45{
46 size_t len;
47
48 if (!need_trap(path))
49 return path;
50
51 len = strlen(path);
52
53 if (len + rootpathlen > PATH_MAX * 2) {
54 errno = ENAMETOOLONG;
55 return NULL;
56 }
57
58 memcpy(buf, rootpath, rootpathlen);
59 strcpy(buf + rootpathlen, path);
60 return buf;
61}
62
63static bool get_rootpath(const char *f)
64{
65 if (rootpath != NULL)
66 return true;
67
68 rootpath = getenv(S_TC_ROOTFS);
69 if (rootpath == NULL) {
70 ERR("TRAP %s(): missing export %s?\n", f, S_TC_ROOTFS);
71 errno = ENOENT;
72 return false;
73 }
74
75 rootpathlen = strlen(rootpath);
76
77 return true;
78}
79
80static void *get_libc_func(const char *f)
81{
82 void *fp;
83
84 if (nextlib == NULL) {
85#ifdef RTLD_NEXT
86 nextlib = RTLD_NEXT;
87#else
88 nextlib = dlopen("libc.so.6", RTLD_LAZY);
89#endif
90 }
91
92 fp = dlsym(nextlib, f);
93 assert(fp);
94
95 return fp;
96}
97
123e8278
MP
98/* wrapper template for a function with one "const char* path" argument */
99#define WRAP_1ARG(rettype, failret, name) \
100TS_EXPORT rettype name(const char *path) \
101{ \
102 const char *p; \
103 char buf[PATH_MAX * 2]; \
104 static rettype (*_fn)(const char*); \
105 \
106 if (!get_rootpath(__func__)) \
107 return failret; \
108 _fn = get_libc_func(#name); \
109 p = trap_path(path, buf); \
110 if (p == NULL) \
111 return failret; \
112 return (*_fn)(p); \
6afc9cd6 113}
7fa8c2d2 114
123e8278
MP
115/* wrapper template for a function with "const char* path" and another argument */
116#define WRAP_2ARGS(rettype, failret, name, arg2t) \
117TS_EXPORT rettype name(const char *path, arg2t arg2) \
118{ \
119 const char *p; \
120 char buf[PATH_MAX * 2]; \
121 static rettype (*_fn)(const char*, arg2t arg2); \
122 \
123 if (!get_rootpath(__func__)) \
124 return failret; \
125 _fn = get_libc_func(#name); \
126 p = trap_path(path, buf); \
127 if (p == NULL) \
128 return failret; \
129 return (*_fn)(p, arg2); \
7fa8c2d2 130}
1426a613 131
123e8278
MP
132/* wrapper template for open family */
133#define WRAP_OPEN(suffix) \
134TS_EXPORT int open ## suffix (const char *path, int flags, ...) \
135{ \
136 const char *p; \
137 char buf[PATH_MAX * 2]; \
138 static int (*_fn)(const char *path, int flags, ...); \
139 \
140 if (!get_rootpath(__func__)) \
141 return -1; \
142 _fn = get_libc_func("open" #suffix); \
143 p = trap_path(path, buf); \
144 if (p == NULL) \
145 return -1; \
146 \
147 if (flags & O_CREAT) { \
148 mode_t mode; \
149 va_list ap; \
150 \
151 va_start(ap, flags); \
152 mode = va_arg(ap, mode_t); \
153 va_end(ap); \
154 return _fn(p, flags, mode); \
155 } \
156 \
157 return _fn(p, flags); \
113d0084
LDM
158}
159
123e8278
MP
160/* wrapper template for __xstat family */
161#define WRAP_VERSTAT(prefix, suffix) \
162TS_EXPORT int prefix ## stat ## suffix (int ver, \
163 const char *path, \
164 struct stat ## suffix *st) \
165{ \
166 const char *p; \
167 char buf[PATH_MAX * 2]; \
168 static int (*_fn)(int ver, const char *path, \
169 struct stat ## suffix *); \
170 _fn = get_libc_func(#prefix "stat" #suffix); \
171 \
172 if (!get_rootpath(__func__)) \
173 return -1; \
174 p = trap_path(path, buf); \
175 if (p == NULL) \
176 return -1; \
177 \
178 return _fn(ver, p, st); \
1426a613
LDM
179}
180
123e8278 181WRAP_1ARG(DIR*, NULL, opendir);
1426a613 182
123e8278
MP
183WRAP_2ARGS(FILE*, NULL, fopen, const char*);
184WRAP_2ARGS(int, -1, mkdir, mode_t);
185WRAP_2ARGS(int, -1, access, int);
186WRAP_2ARGS(int, -1, stat, struct stat*);
187WRAP_2ARGS(int, -1, stat64, struct stat64*);
188WRAP_2ARGS(int, -1, lstat, struct stat*);
189WRAP_2ARGS(int, -1, lstat64, struct stat64*);
1426a613 190
123e8278
MP
191WRAP_OPEN();
192WRAP_OPEN(64);
1426a613 193
123e8278
MP
194#ifdef HAVE___XSTAT
195WRAP_VERSTAT(__x,);
196WRAP_VERSTAT(__x,64);
197WRAP_VERSTAT(__lx,);
198WRAP_VERSTAT(__lx,64);
d005aeb7 199#endif