libkmod: fix return error when opening index
[platform/upstream/kmod.git] / testsuite / path.c
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 #include <assert.h>
19 #include <dirent.h>
20 #include <dlfcn.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 #include <shared/util.h>
33
34 #include "testsuite.h"
35
36 static void *nextlib;
37 static const char *rootpath;
38 static size_t rootpathlen;
39
40 static inline bool need_trap(const char *path)
41 {
42         return path != NULL && path[0] == '/'
43                 && !strstartswith(path, ABS_TOP_BUILDDIR);
44 }
45
46 static 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
65 static 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
82 static 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
100 /* wrapper template for a function with one "const char* path" argument */
101 #define WRAP_1ARG(rettype, failret, name) \
102 TS_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);                       \
115 }
116
117 /* wrapper template for a function with "const char* path" and another argument */
118 #define WRAP_2ARGS(rettype, failret, name, arg2t)       \
119 TS_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);                         \
132 }
133
134 /* wrapper template for open family */
135 #define WRAP_OPEN(suffix)                                       \
136 TS_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);                                   \
160 }
161
162 /* wrapper template for __xstat family */
163 #define WRAP_VERSTAT(prefix, suffix)                        \
164 TS_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);                             \
181 }
182
183 WRAP_1ARG(DIR*, NULL, opendir);
184
185 WRAP_2ARGS(FILE*, NULL, fopen, const char*);
186 WRAP_2ARGS(int, -1, mkdir, mode_t);
187 WRAP_2ARGS(int, -1, access, int);
188 WRAP_2ARGS(int, -1, stat, struct stat*);
189 WRAP_2ARGS(int, -1, lstat, struct stat*);
190 #ifndef _FILE_OFFSET_BITS
191 WRAP_2ARGS(int, -1, stat64, struct stat64*);
192 WRAP_2ARGS(int, -1, lstat64, struct stat64*);
193 WRAP_OPEN(64);
194 #endif
195
196 WRAP_OPEN();
197
198 #ifdef HAVE___XSTAT
199 WRAP_VERSTAT(__x,);
200 WRAP_VERSTAT(__lx,);
201 #ifndef _FILE_OFFSET_BITS
202 WRAP_VERSTAT(__x,64);
203 WRAP_VERSTAT(__lx,64);
204 #endif
205 #endif