blob: fa5fcebd18a15f79592ab02647c2164764f326b0 [file] [log] [blame]
Lucas De Marchie701e382012-01-26 17:01:41 -02001/*
Lucas De Marchie6b0e492013-01-16 11:27:21 -02002 * Copyright (C) 2012-2013 ProFUSION embedded systems
Lucas De Marchie701e382012-01-26 17:01:41 -02003 *
Lucas De Marchie1b1ab22012-07-10 09:42:24 -03004 * 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.
Lucas De Marchie701e382012-01-26 17:01:41 -02008 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Lucas De Marchie1b1ab22012-07-10 09:42:24 -030011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
Lucas De Marchie701e382012-01-26 17:01:41 -020013 *
Lucas De Marchie1b1ab22012-07-10 09:42:24 -030014 * You should have received a copy of the GNU Lesser General Public
Lucas De Marchidea2dfe2014-12-25 23:32:03 -020015 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Lucas De Marchie701e382012-01-26 17:01:41 -020016 */
17
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -020018#include <assert.h>
Lucas De Marchi4e36cb12012-01-25 12:42:13 -020019#include <dirent.h>
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -020020#include <dlfcn.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030021#include <errno.h>
22#include <fcntl.h>
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -020023#include <limits.h>
Lucas De Marchi7fa8c2d2012-01-25 11:36:28 -020024#include <stdarg.h>
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -020025#include <stdio.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030026#include <stdlib.h>
27#include <string.h>
Lucas De Marchi1426a612012-01-25 12:22:50 -020028#include <unistd.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030029#include <sys/stat.h>
30#include <sys/types.h>
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -020031
Lucas De Marchi8ff7f002015-01-07 19:14:20 -020032#include <shared/util.h>
33
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -020034#include "testsuite.h"
35
36static void *nextlib;
37static const char *rootpath;
38static size_t rootpathlen;
39
40static inline bool need_trap(const char *path)
41{
Lucas De Marchi8ff7f002015-01-07 19:14:20 -020042 return path != NULL && path[0] == '/'
43 && !strstartswith(path, ABS_TOP_BUILDDIR);
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -020044}
45
46static const char *trap_path(const char *path, char buf[PATH_MAX * 2])
47{
48 size_t len;
49
50 if (!need_trap(path))
51 return path;
52
53 len = strlen(path);
54
55 if (len + rootpathlen > PATH_MAX * 2) {
56 errno = ENAMETOOLONG;
57 return NULL;
58 }
59
60 memcpy(buf, rootpath, rootpathlen);
61 strcpy(buf + rootpathlen, path);
62 return buf;
63}
64
65static bool get_rootpath(const char *f)
66{
67 if (rootpath != NULL)
68 return true;
69
70 rootpath = getenv(S_TC_ROOTFS);
71 if (rootpath == NULL) {
72 ERR("TRAP %s(): missing export %s?\n", f, S_TC_ROOTFS);
73 errno = ENOENT;
74 return false;
75 }
76
77 rootpathlen = strlen(rootpath);
78
79 return true;
80}
81
82static void *get_libc_func(const char *f)
83{
84 void *fp;
85
86 if (nextlib == NULL) {
87#ifdef RTLD_NEXT
88 nextlib = RTLD_NEXT;
89#else
90 nextlib = dlopen("libc.so.6", RTLD_LAZY);
91#endif
92 }
93
94 fp = dlsym(nextlib, f);
95 assert(fp);
96
97 return fp;
98}
99
Martin Pitt123e8272012-08-01 23:35:34 +0200100/* wrapper template for a function with one "const char* path" argument */
101#define WRAP_1ARG(rettype, failret, name) \
102TS_EXPORT rettype name(const char *path) \
103{ \
104 const char *p; \
105 char buf[PATH_MAX * 2]; \
106 static rettype (*_fn)(const char*); \
107 \
108 if (!get_rootpath(__func__)) \
109 return failret; \
110 _fn = get_libc_func(#name); \
111 p = trap_path(path, buf); \
112 if (p == NULL) \
113 return failret; \
114 return (*_fn)(p); \
Lucas De Marchi6afc9cd2012-01-25 02:44:45 -0200115}
Lucas De Marchi7fa8c2d2012-01-25 11:36:28 -0200116
Martin Pitt123e8272012-08-01 23:35:34 +0200117/* wrapper template for a function with "const char* path" and another argument */
118#define WRAP_2ARGS(rettype, failret, name, arg2t) \
119TS_EXPORT rettype name(const char *path, arg2t arg2) \
120{ \
121 const char *p; \
122 char buf[PATH_MAX * 2]; \
123 static rettype (*_fn)(const char*, arg2t arg2); \
124 \
125 if (!get_rootpath(__func__)) \
126 return failret; \
127 _fn = get_libc_func(#name); \
128 p = trap_path(path, buf); \
129 if (p == NULL) \
130 return failret; \
131 return (*_fn)(p, arg2); \
Lucas De Marchi7fa8c2d2012-01-25 11:36:28 -0200132}
Lucas De Marchi1426a612012-01-25 12:22:50 -0200133
Martin Pitt123e8272012-08-01 23:35:34 +0200134/* wrapper template for open family */
135#define WRAP_OPEN(suffix) \
136TS_EXPORT int open ## suffix (const char *path, int flags, ...) \
137{ \
138 const char *p; \
139 char buf[PATH_MAX * 2]; \
140 static int (*_fn)(const char *path, int flags, ...); \
141 \
142 if (!get_rootpath(__func__)) \
143 return -1; \
144 _fn = get_libc_func("open" #suffix); \
145 p = trap_path(path, buf); \
146 if (p == NULL) \
147 return -1; \
148 \
149 if (flags & O_CREAT) { \
150 mode_t mode; \
151 va_list ap; \
152 \
153 va_start(ap, flags); \
154 mode = va_arg(ap, mode_t); \
155 va_end(ap); \
156 return _fn(p, flags, mode); \
157 } \
158 \
159 return _fn(p, flags); \
Lucas De Marchi113d0082012-05-24 01:58:54 -0300160}
161
Martin Pitt123e8272012-08-01 23:35:34 +0200162/* wrapper template for __xstat family */
163#define WRAP_VERSTAT(prefix, suffix) \
164TS_EXPORT int prefix ## stat ## suffix (int ver, \
165 const char *path, \
166 struct stat ## suffix *st) \
167{ \
168 const char *p; \
169 char buf[PATH_MAX * 2]; \
170 static int (*_fn)(int ver, const char *path, \
171 struct stat ## suffix *); \
172 _fn = get_libc_func(#prefix "stat" #suffix); \
173 \
174 if (!get_rootpath(__func__)) \
175 return -1; \
176 p = trap_path(path, buf); \
177 if (p == NULL) \
178 return -1; \
179 \
180 return _fn(ver, p, st); \
Lucas De Marchi1426a612012-01-25 12:22:50 -0200181}
182
Martin Pitt123e8272012-08-01 23:35:34 +0200183WRAP_1ARG(DIR*, NULL, opendir);
184
185WRAP_2ARGS(FILE*, NULL, fopen, const char*);
186WRAP_2ARGS(int, -1, mkdir, mode_t);
187WRAP_2ARGS(int, -1, access, int);
188WRAP_2ARGS(int, -1, stat, struct stat*);
Martin Pitt123e8272012-08-01 23:35:34 +0200189WRAP_2ARGS(int, -1, lstat, struct stat*);
Lucas De Marchid6423412012-09-07 14:59:35 -0300190#ifndef _FILE_OFFSET_BITS
191WRAP_2ARGS(int, -1, stat64, struct stat64*);
Martin Pitt123e8272012-08-01 23:35:34 +0200192WRAP_2ARGS(int, -1, lstat64, struct stat64*);
Lucas De Marchid6423412012-09-07 14:59:35 -0300193WRAP_OPEN(64);
194#endif
Martin Pitt123e8272012-08-01 23:35:34 +0200195
196WRAP_OPEN();
Martin Pitt123e8272012-08-01 23:35:34 +0200197
Lucas De Marchid005aeb2012-02-08 20:29:52 -0200198#ifdef HAVE___XSTAT
Martin Pitt123e8272012-08-01 23:35:34 +0200199WRAP_VERSTAT(__x,);
Martin Pitt123e8272012-08-01 23:35:34 +0200200WRAP_VERSTAT(__lx,);
Lucas De Marchid6423412012-09-07 14:59:35 -0300201#ifndef _FILE_OFFSET_BITS
202WRAP_VERSTAT(__x,64);
Martin Pitt123e8272012-08-01 23:35:34 +0200203WRAP_VERSTAT(__lx,64);
Lucas De Marchid005aeb2012-02-08 20:29:52 -0200204#endif
Lucas De Marchid6423412012-09-07 14:59:35 -0300205#endif