]>
Commit | Line | Data |
---|---|---|
6afc9cd6 LDM |
1 | #include <assert.h> |
2 | #include <errno.h> | |
7fa8c2d2 | 3 | #include <fcntl.h> |
6afc9cd6 LDM |
4 | #include <dlfcn.h> |
5 | #include <limits.h> | |
6 | #include <stdlib.h> | |
7fa8c2d2 | 7 | #include <stdarg.h> |
6afc9cd6 LDM |
8 | #include <string.h> |
9 | #include <stdio.h> | |
7fa8c2d2 LDM |
10 | #include <sys/types.h> |
11 | #include <sys/stat.h> | |
6afc9cd6 LDM |
12 | |
13 | #include "testsuite.h" | |
14 | ||
15 | static void *nextlib; | |
16 | static const char *rootpath; | |
17 | static size_t rootpathlen; | |
18 | ||
19 | static inline bool need_trap(const char *path) | |
20 | { | |
21 | return path != NULL && path[0] == '/'; | |
22 | } | |
23 | ||
24 | static const char *trap_path(const char *path, char buf[PATH_MAX * 2]) | |
25 | { | |
26 | size_t len; | |
27 | ||
28 | if (!need_trap(path)) | |
29 | return path; | |
30 | ||
31 | len = strlen(path); | |
32 | ||
33 | if (len + rootpathlen > PATH_MAX * 2) { | |
34 | errno = ENAMETOOLONG; | |
35 | return NULL; | |
36 | } | |
37 | ||
38 | memcpy(buf, rootpath, rootpathlen); | |
39 | strcpy(buf + rootpathlen, path); | |
40 | return buf; | |
41 | } | |
42 | ||
43 | static bool get_rootpath(const char *f) | |
44 | { | |
45 | if (rootpath != NULL) | |
46 | return true; | |
47 | ||
48 | rootpath = getenv(S_TC_ROOTFS); | |
49 | if (rootpath == NULL) { | |
50 | ERR("TRAP %s(): missing export %s?\n", f, S_TC_ROOTFS); | |
51 | errno = ENOENT; | |
52 | return false; | |
53 | } | |
54 | ||
55 | rootpathlen = strlen(rootpath); | |
56 | ||
57 | return true; | |
58 | } | |
59 | ||
60 | static void *get_libc_func(const char *f) | |
61 | { | |
62 | void *fp; | |
63 | ||
64 | if (nextlib == NULL) { | |
65 | #ifdef RTLD_NEXT | |
66 | nextlib = RTLD_NEXT; | |
67 | #else | |
68 | nextlib = dlopen("libc.so.6", RTLD_LAZY); | |
69 | #endif | |
70 | } | |
71 | ||
72 | fp = dlsym(nextlib, f); | |
73 | assert(fp); | |
74 | ||
75 | return fp; | |
76 | } | |
77 | ||
78 | TS_EXPORT FILE *fopen(const char *path, const char *mode) | |
79 | { | |
80 | const char *p; | |
81 | char buf[PATH_MAX * 2]; | |
82 | static int (*_fopen)(const char *path, const char *mode); | |
83 | ||
84 | if (!get_rootpath(__func__)) | |
85 | return NULL; | |
86 | ||
87 | _fopen = get_libc_func("fopen"); | |
88 | ||
89 | p = trap_path(path, buf); | |
90 | if (p == NULL) | |
91 | return NULL; | |
92 | ||
93 | return (void *) (long) (*_fopen)(p, mode); | |
94 | } | |
7fa8c2d2 LDM |
95 | |
96 | TS_EXPORT int open(const char *path, int flags, ...) | |
97 | { | |
98 | const char *p; | |
99 | char buf[PATH_MAX * 2]; | |
100 | static int (*_open)(const char *path, int flags, ...); | |
101 | ||
102 | if (!get_rootpath(__func__)) | |
103 | return -1; | |
104 | ||
105 | _open = get_libc_func("open"); | |
106 | p = trap_path(path, buf); | |
107 | if (p == NULL) | |
108 | return -1; | |
109 | ||
110 | if (flags & O_CREAT) { | |
111 | mode_t mode; | |
112 | va_list ap; | |
113 | ||
114 | va_start(ap, flags); | |
115 | mode = va_arg(ap, mode_t); | |
116 | va_end(ap); | |
117 | _open(p, flags, mode); | |
118 | } | |
119 | ||
120 | return _open(p, flags); | |
121 | } |