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 /* We unset _FILE_OFFSET_BITS here so we can override both stat and stat64 on
19*cc4ad7daSAndroid Build Coastguard Worker * 32-bit architectures and forward each to the right libc function */
20*cc4ad7daSAndroid Build Coastguard Worker #undef _FILE_OFFSET_BITS
21*cc4ad7daSAndroid Build Coastguard Worker
22*cc4ad7daSAndroid Build Coastguard Worker #include <assert.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <dlfcn.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <fcntl.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
32*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
33*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
34*cc4ad7daSAndroid Build Coastguard Worker #include <sys/types.h>
35*cc4ad7daSAndroid Build Coastguard Worker
36*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
37*cc4ad7daSAndroid Build Coastguard Worker
38*cc4ad7daSAndroid Build Coastguard Worker #include "testsuite.h"
39*cc4ad7daSAndroid Build Coastguard Worker
40*cc4ad7daSAndroid Build Coastguard Worker static void *nextlib;
41*cc4ad7daSAndroid Build Coastguard Worker static const char *rootpath;
42*cc4ad7daSAndroid Build Coastguard Worker static size_t rootpathlen;
43*cc4ad7daSAndroid Build Coastguard Worker
need_trap(const char * path)44*cc4ad7daSAndroid Build Coastguard Worker static inline bool need_trap(const char *path)
45*cc4ad7daSAndroid Build Coastguard Worker {
46*cc4ad7daSAndroid Build Coastguard Worker return path != NULL && path[0] == '/'
47*cc4ad7daSAndroid Build Coastguard Worker && !strstartswith(path, ABS_TOP_BUILDDIR);
48*cc4ad7daSAndroid Build Coastguard Worker }
49*cc4ad7daSAndroid Build Coastguard Worker
trap_path(const char * path,char buf[PATH_MAX * 2])50*cc4ad7daSAndroid Build Coastguard Worker static const char *trap_path(const char *path, char buf[PATH_MAX * 2])
51*cc4ad7daSAndroid Build Coastguard Worker {
52*cc4ad7daSAndroid Build Coastguard Worker size_t len;
53*cc4ad7daSAndroid Build Coastguard Worker
54*cc4ad7daSAndroid Build Coastguard Worker if (!need_trap(path))
55*cc4ad7daSAndroid Build Coastguard Worker return path;
56*cc4ad7daSAndroid Build Coastguard Worker
57*cc4ad7daSAndroid Build Coastguard Worker len = strlen(path);
58*cc4ad7daSAndroid Build Coastguard Worker
59*cc4ad7daSAndroid Build Coastguard Worker if (len + rootpathlen > PATH_MAX * 2) {
60*cc4ad7daSAndroid Build Coastguard Worker errno = ENAMETOOLONG;
61*cc4ad7daSAndroid Build Coastguard Worker return NULL;
62*cc4ad7daSAndroid Build Coastguard Worker }
63*cc4ad7daSAndroid Build Coastguard Worker
64*cc4ad7daSAndroid Build Coastguard Worker memcpy(buf, rootpath, rootpathlen);
65*cc4ad7daSAndroid Build Coastguard Worker strcpy(buf + rootpathlen, path);
66*cc4ad7daSAndroid Build Coastguard Worker return buf;
67*cc4ad7daSAndroid Build Coastguard Worker }
68*cc4ad7daSAndroid Build Coastguard Worker
get_rootpath(const char * f)69*cc4ad7daSAndroid Build Coastguard Worker static bool get_rootpath(const char *f)
70*cc4ad7daSAndroid Build Coastguard Worker {
71*cc4ad7daSAndroid Build Coastguard Worker if (rootpath != NULL)
72*cc4ad7daSAndroid Build Coastguard Worker return true;
73*cc4ad7daSAndroid Build Coastguard Worker
74*cc4ad7daSAndroid Build Coastguard Worker rootpath = getenv(S_TC_ROOTFS);
75*cc4ad7daSAndroid Build Coastguard Worker if (rootpath == NULL) {
76*cc4ad7daSAndroid Build Coastguard Worker ERR("TRAP %s(): missing export %s?\n", f, S_TC_ROOTFS);
77*cc4ad7daSAndroid Build Coastguard Worker errno = ENOENT;
78*cc4ad7daSAndroid Build Coastguard Worker return false;
79*cc4ad7daSAndroid Build Coastguard Worker }
80*cc4ad7daSAndroid Build Coastguard Worker
81*cc4ad7daSAndroid Build Coastguard Worker rootpathlen = strlen(rootpath);
82*cc4ad7daSAndroid Build Coastguard Worker
83*cc4ad7daSAndroid Build Coastguard Worker return true;
84*cc4ad7daSAndroid Build Coastguard Worker }
85*cc4ad7daSAndroid Build Coastguard Worker
get_libc_func(const char * f)86*cc4ad7daSAndroid Build Coastguard Worker static void *get_libc_func(const char *f)
87*cc4ad7daSAndroid Build Coastguard Worker {
88*cc4ad7daSAndroid Build Coastguard Worker void *fp;
89*cc4ad7daSAndroid Build Coastguard Worker
90*cc4ad7daSAndroid Build Coastguard Worker if (nextlib == NULL) {
91*cc4ad7daSAndroid Build Coastguard Worker #ifdef RTLD_NEXT
92*cc4ad7daSAndroid Build Coastguard Worker nextlib = RTLD_NEXT;
93*cc4ad7daSAndroid Build Coastguard Worker #else
94*cc4ad7daSAndroid Build Coastguard Worker nextlib = dlopen("libc.so.6", RTLD_LAZY);
95*cc4ad7daSAndroid Build Coastguard Worker #endif
96*cc4ad7daSAndroid Build Coastguard Worker }
97*cc4ad7daSAndroid Build Coastguard Worker
98*cc4ad7daSAndroid Build Coastguard Worker fp = dlsym(nextlib, f);
99*cc4ad7daSAndroid Build Coastguard Worker assert(fp);
100*cc4ad7daSAndroid Build Coastguard Worker
101*cc4ad7daSAndroid Build Coastguard Worker return fp;
102*cc4ad7daSAndroid Build Coastguard Worker }
103*cc4ad7daSAndroid Build Coastguard Worker
104*cc4ad7daSAndroid Build Coastguard Worker /* wrapper template for a function with one "const char* path" argument */
105*cc4ad7daSAndroid Build Coastguard Worker #define WRAP_1ARG(rettype, failret, name) \
106*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT rettype name(const char *path) \
107*cc4ad7daSAndroid Build Coastguard Worker { \
108*cc4ad7daSAndroid Build Coastguard Worker const char *p; \
109*cc4ad7daSAndroid Build Coastguard Worker char buf[PATH_MAX * 2]; \
110*cc4ad7daSAndroid Build Coastguard Worker static rettype (*_fn)(const char*); \
111*cc4ad7daSAndroid Build Coastguard Worker \
112*cc4ad7daSAndroid Build Coastguard Worker if (!get_rootpath(__func__)) \
113*cc4ad7daSAndroid Build Coastguard Worker return failret; \
114*cc4ad7daSAndroid Build Coastguard Worker _fn = get_libc_func(#name); \
115*cc4ad7daSAndroid Build Coastguard Worker p = trap_path(path, buf); \
116*cc4ad7daSAndroid Build Coastguard Worker if (p == NULL) \
117*cc4ad7daSAndroid Build Coastguard Worker return failret; \
118*cc4ad7daSAndroid Build Coastguard Worker return (*_fn)(p); \
119*cc4ad7daSAndroid Build Coastguard Worker }
120*cc4ad7daSAndroid Build Coastguard Worker
121*cc4ad7daSAndroid Build Coastguard Worker /* wrapper template for a function with "const char* path" and another argument */
122*cc4ad7daSAndroid Build Coastguard Worker #define WRAP_2ARGS(rettype, failret, name, arg2t) \
123*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT rettype name(const char *path, arg2t arg2) \
124*cc4ad7daSAndroid Build Coastguard Worker { \
125*cc4ad7daSAndroid Build Coastguard Worker const char *p; \
126*cc4ad7daSAndroid Build Coastguard Worker char buf[PATH_MAX * 2]; \
127*cc4ad7daSAndroid Build Coastguard Worker static rettype (*_fn)(const char*, arg2t arg2); \
128*cc4ad7daSAndroid Build Coastguard Worker \
129*cc4ad7daSAndroid Build Coastguard Worker if (!get_rootpath(__func__)) \
130*cc4ad7daSAndroid Build Coastguard Worker return failret; \
131*cc4ad7daSAndroid Build Coastguard Worker _fn = get_libc_func(#name); \
132*cc4ad7daSAndroid Build Coastguard Worker p = trap_path(path, buf); \
133*cc4ad7daSAndroid Build Coastguard Worker if (p == NULL) \
134*cc4ad7daSAndroid Build Coastguard Worker return failret; \
135*cc4ad7daSAndroid Build Coastguard Worker return (*_fn)(p, arg2); \
136*cc4ad7daSAndroid Build Coastguard Worker }
137*cc4ad7daSAndroid Build Coastguard Worker
138*cc4ad7daSAndroid Build Coastguard Worker /* wrapper template for open family */
139*cc4ad7daSAndroid Build Coastguard Worker #define WRAP_OPEN(suffix) \
140*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT int open ## suffix (const char *path, int flags, ...) \
141*cc4ad7daSAndroid Build Coastguard Worker { \
142*cc4ad7daSAndroid Build Coastguard Worker const char *p; \
143*cc4ad7daSAndroid Build Coastguard Worker char buf[PATH_MAX * 2]; \
144*cc4ad7daSAndroid Build Coastguard Worker static int (*_fn)(const char *path, int flags, ...); \
145*cc4ad7daSAndroid Build Coastguard Worker \
146*cc4ad7daSAndroid Build Coastguard Worker if (!get_rootpath(__func__)) \
147*cc4ad7daSAndroid Build Coastguard Worker return -1; \
148*cc4ad7daSAndroid Build Coastguard Worker _fn = get_libc_func("open" #suffix); \
149*cc4ad7daSAndroid Build Coastguard Worker p = trap_path(path, buf); \
150*cc4ad7daSAndroid Build Coastguard Worker if (p == NULL) \
151*cc4ad7daSAndroid Build Coastguard Worker return -1; \
152*cc4ad7daSAndroid Build Coastguard Worker \
153*cc4ad7daSAndroid Build Coastguard Worker if (flags & O_CREAT) { \
154*cc4ad7daSAndroid Build Coastguard Worker mode_t mode; \
155*cc4ad7daSAndroid Build Coastguard Worker va_list ap; \
156*cc4ad7daSAndroid Build Coastguard Worker \
157*cc4ad7daSAndroid Build Coastguard Worker va_start(ap, flags); \
158*cc4ad7daSAndroid Build Coastguard Worker mode = va_arg(ap, mode_t); \
159*cc4ad7daSAndroid Build Coastguard Worker va_end(ap); \
160*cc4ad7daSAndroid Build Coastguard Worker return _fn(p, flags, mode); \
161*cc4ad7daSAndroid Build Coastguard Worker } \
162*cc4ad7daSAndroid Build Coastguard Worker \
163*cc4ad7daSAndroid Build Coastguard Worker return _fn(p, flags); \
164*cc4ad7daSAndroid Build Coastguard Worker }
165*cc4ad7daSAndroid Build Coastguard Worker
166*cc4ad7daSAndroid Build Coastguard Worker /*
167*cc4ad7daSAndroid Build Coastguard Worker * wrapper template for __xstat family
168*cc4ad7daSAndroid Build Coastguard Worker * This family got deprecated/dropped in glibc 2.32.9000, but we still need
169*cc4ad7daSAndroid Build Coastguard Worker * to keep it for a while for programs that were built against previous versions
170*cc4ad7daSAndroid Build Coastguard Worker */
171*cc4ad7daSAndroid Build Coastguard Worker #define WRAP_VERSTAT(prefix, suffix) \
172*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT int prefix ## stat ## suffix (int ver, \
173*cc4ad7daSAndroid Build Coastguard Worker const char *path, \
174*cc4ad7daSAndroid Build Coastguard Worker struct stat ## suffix *st); \
175*cc4ad7daSAndroid Build Coastguard Worker TS_EXPORT int prefix ## stat ## suffix (int ver, \
176*cc4ad7daSAndroid Build Coastguard Worker const char *path, \
177*cc4ad7daSAndroid Build Coastguard Worker struct stat ## suffix *st) \
178*cc4ad7daSAndroid Build Coastguard Worker { \
179*cc4ad7daSAndroid Build Coastguard Worker const char *p; \
180*cc4ad7daSAndroid Build Coastguard Worker char buf[PATH_MAX * 2]; \
181*cc4ad7daSAndroid Build Coastguard Worker static int (*_fn)(int ver, const char *path, \
182*cc4ad7daSAndroid Build Coastguard Worker struct stat ## suffix *); \
183*cc4ad7daSAndroid Build Coastguard Worker _fn = get_libc_func(#prefix "stat" #suffix); \
184*cc4ad7daSAndroid Build Coastguard Worker \
185*cc4ad7daSAndroid Build Coastguard Worker if (!get_rootpath(__func__)) \
186*cc4ad7daSAndroid Build Coastguard Worker return -1; \
187*cc4ad7daSAndroid Build Coastguard Worker p = trap_path(path, buf); \
188*cc4ad7daSAndroid Build Coastguard Worker if (p == NULL) \
189*cc4ad7daSAndroid Build Coastguard Worker return -1; \
190*cc4ad7daSAndroid Build Coastguard Worker \
191*cc4ad7daSAndroid Build Coastguard Worker return _fn(ver, p, st); \
192*cc4ad7daSAndroid Build Coastguard Worker }
193*cc4ad7daSAndroid Build Coastguard Worker
194*cc4ad7daSAndroid Build Coastguard Worker WRAP_1ARG(DIR*, NULL, opendir);
195*cc4ad7daSAndroid Build Coastguard Worker WRAP_1ARG(int, -1, chdir);
196*cc4ad7daSAndroid Build Coastguard Worker
197*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(FILE*, NULL, fopen, const char*);
198*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(FILE*, NULL, fopen64, const char*);
199*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(int, -1, mkdir, mode_t);
200*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(int, -1, access, int);
201*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(int, -1, stat, struct stat*);
202*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(int, -1, lstat, struct stat*);
203*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(int, -1, stat64, struct stat64*);
204*cc4ad7daSAndroid Build Coastguard Worker WRAP_2ARGS(int, -1, lstat64, struct stat64*);
205*cc4ad7daSAndroid Build Coastguard Worker WRAP_OPEN(64);
206*cc4ad7daSAndroid Build Coastguard Worker
207*cc4ad7daSAndroid Build Coastguard Worker WRAP_OPEN();
208*cc4ad7daSAndroid Build Coastguard Worker
209*cc4ad7daSAndroid Build Coastguard Worker #ifdef HAVE___XSTAT
210*cc4ad7daSAndroid Build Coastguard Worker WRAP_VERSTAT(__x,);
211*cc4ad7daSAndroid Build Coastguard Worker WRAP_VERSTAT(__lx,);
212*cc4ad7daSAndroid Build Coastguard Worker WRAP_VERSTAT(__x,64);
213*cc4ad7daSAndroid Build Coastguard Worker WRAP_VERSTAT(__lx,64);
214*cc4ad7daSAndroid Build Coastguard Worker #endif
215