backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / virmockstathelpers.c
blob0bbea4b4373a7602c37ecc1d98970cc1aed4a1d4
1 /*
2 * Copyright (C) 2019 Red Hat, Inc.
4 * This library 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.
9 * This library 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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
18 * Helpers for dealing with the many variants of stat(). This
19 * C file should be included from any file that wants to mock
20 * stat() correctly.
23 #include "virmock.h"
24 #include "viralloc.h"
26 #include <sys/stat.h>
27 #include <unistd.h>
30 * The POSIX stat() function might resolve to any number of different
31 * symbols in the C library.
33 * The may be an additional stat64() function exposed by the headers
34 * too.
36 * On 64-bit hosts the stat & stat64 functions are identical, always
37 * refering to the 64-bit ABI.
39 * On 32-bit hosts they refer to the 32-bit & 64-bit ABIs respectively.
41 * Libvirt uses _FILE_OFFSET_BITS=64 on 32-bit hosts, which causes the
42 * C library to transparently rewrite stat() calls to be stat64() calls.
43 * Libvirt will never see the 32-bit ABI from the traditional stat()
44 * call. We cannot assume this rewriting is done using a macro. It might
45 * be, but on GLibC it is done with a magic __asm__ statement to apply
46 * the rewrite at link time instead of at preprocessing.
48 * In GLibC there may be two additional functions exposed by the headers,
49 * __xstat() and __xstat64(). When these exist, stat() and stat64() are
50 * transparently rewritten to call __xstat() and __xstat64() respectively.
51 * The former symbols will not actally exist in the library at all, only
52 * the header. The leading "__" indicates the symbols are a private impl
53 * detail of the C library that applications should not care about.
54 * Unfortunately, because we are trying to mock replace the C library,
55 * we need to know about this internal impl detail.
57 * With all this in mind the list of functions we have to mock will depend
58 * on several factors
60 * - If _FILE_OFFSET_BITS is set, then we are on a 32-bit host, and we
61 * only need to mock stat64 and __xstat64. The other stat / __xstat
62 * functions exist, but we'll never call them so they can be ignored
63 * for mocking.
65 * - If _FILE_OFFSET_BITS is not set, then we are on a 64-bit host and
66 * we should mock stat, stat64, __xstat & __xstat64. Either may be
67 * called by app code.
69 * - If __xstat & __xstat64 exist, then stat & stat64 will not exist
70 * as symbols in the library, so the latter should not be mocked.
72 * The same all applies to lstat()
77 #if defined(HAVE_STAT) && !defined(HAVE___XSTAT) && !defined(_FILE_OFFSET_BITS)
78 # define MOCK_STAT
79 #endif
80 #if defined(HAVE_STAT64) && !defined(HAVE___XSTAT64)
81 # define MOCK_STAT64
82 #endif
83 #if defined(HAVE___XSTAT) && !defined(_FILE_OFFSET_BITS)
84 # define MOCK___XSTAT
85 #endif
86 #if defined(HAVE___XSTAT64)
87 # define MOCK___XSTAT64
88 #endif
89 #if defined(HAVE_LSTAT) && !defined(HAVE___LXSTAT) && !defined(_FILE_OFFSET_BITS)
90 # define MOCK_LSTAT
91 #endif
92 #if defined(HAVE_LSTAT64) && !defined(HAVE___LXSTAT64)
93 # define MOCK_LSTAT64
94 #endif
95 #if defined(HAVE___LXSTAT) && !defined(_FILE_OFFSET_BITS)
96 # define MOCK___LXSTAT
97 #endif
98 #if defined(HAVE___LXSTAT64)
99 # define MOCK___LXSTAT64
100 #endif
102 #ifdef MOCK_STAT
103 static int (*real_stat)(const char *path, struct stat *sb);
104 #endif
105 #ifdef MOCK_STAT64
106 static int (*real_stat64)(const char *path, struct stat64 *sb);
107 #endif
108 #ifdef MOCK___XSTAT
109 static int (*real___xstat)(int ver, const char *path, struct stat *sb);
110 #endif
111 #ifdef MOCK___XSTAT64
112 static int (*real___xstat64)(int ver, const char *path, struct stat64 *sb);
113 #endif
114 #ifdef MOCK_LSTAT
115 static int (*real_lstat)(const char *path, struct stat *sb);
116 #endif
117 #ifdef MOCK_LSTAT64
118 static int (*real_lstat64)(const char *path, struct stat64 *sb);
119 #endif
120 #ifdef MOCK___LXSTAT
121 static int (*real___lxstat)(int ver, const char *path, struct stat *sb);
122 #endif
123 #ifdef MOCK___LXSTAT64
124 static int (*real___lxstat64)(int ver, const char *path, struct stat64 *sb);
125 #endif
127 static bool init;
128 static bool debug;
130 #define fdebug(msg, ...) do { if (debug) fprintf(stderr, msg, __VA_ARGS__); } while (0)
132 static void virMockStatInit(void)
134 if (init)
135 return;
137 init = true;
138 debug = getenv("VIR_MOCK_STAT_DEBUG");
140 #ifdef MOCK_STAT
141 VIR_MOCK_REAL_INIT(stat);
142 fdebug("real stat %p\n", real_stat);
143 #endif
144 #ifdef MOCK_STAT64
145 VIR_MOCK_REAL_INIT(stat64);
146 fdebug("real stat64 %p\n", real_stat64);
147 #endif
148 #ifdef MOCK___XSTAT
149 VIR_MOCK_REAL_INIT(__xstat);
150 fdebug("real __xstat %p\n", real___xstat);
151 #endif
152 #ifdef MOCK___XSTAT64
153 VIR_MOCK_REAL_INIT(__xstat64);
154 fdebug("real __xstat64 %p\n", real___xstat64);
155 #endif
156 #ifdef MOCK_LSTAT
157 VIR_MOCK_REAL_INIT(lstat);
158 fdebug("real lstat %p\n", real_lstat);
159 #endif
160 #ifdef MOCK_LSTAT64
161 VIR_MOCK_REAL_INIT(lstat64);
162 fdebug("real lstat64 %p\n", real_lstat64);
163 #endif
164 #ifdef MOCK___LXSTAT
165 VIR_MOCK_REAL_INIT(__lxstat);
166 fdebug("real __lxstat %p\n", real___lxstat);
167 #endif
168 #ifdef MOCK___LXSTAT64
169 VIR_MOCK_REAL_INIT(__lxstat64);
170 fdebug("real __lxstat64 %p\n", real___lxstat64);
171 #endif
175 * @stat: the path being queried
176 * @newpath: fill with redirected path, or leave NULL to use orig path
178 * Return 0 on success, -1 on allocation error
180 static int virMockStatRedirect(const char *path, char **newpath);
182 #ifndef VIR_MOCK_STAT_HOOK
183 # define VIR_MOCK_STAT_HOOK do { } while (0)
184 #endif
186 #ifdef MOCK_STAT
187 int stat(const char *path, struct stat *sb)
189 VIR_AUTOFREE(char *) newpath = NULL;
191 virMockStatInit();
193 if (virMockStatRedirect(path, &newpath) < 0)
194 abort();
195 fdebug("stat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
197 VIR_MOCK_STAT_HOOK;
199 return real_stat(newpath ? newpath : path, sb);
201 #endif
203 #ifdef MOCK_STAT64
204 int stat64(const char *path, struct stat64 *sb)
206 VIR_AUTOFREE(char *) newpath = NULL;
208 virMockStatInit();
210 if (virMockStatRedirect(path, &newpath) < 0)
211 abort();
212 fdebug("stat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
214 VIR_MOCK_STAT_HOOK;
216 return real_stat64(newpath ? newpath : path, sb);
218 #endif
220 #ifdef MOCK___XSTAT
222 __xstat(int ver, const char *path, struct stat *sb)
224 VIR_AUTOFREE(char *) newpath = NULL;
226 virMockStatInit();
228 if (virMockStatRedirect(path, &newpath) < 0)
229 abort();
230 fdebug("__xstat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
232 VIR_MOCK_STAT_HOOK;
234 return real___xstat(ver, newpath ? newpath : path, sb);
236 #endif
238 #ifdef MOCK___XSTAT64
240 __xstat64(int ver, const char *path, struct stat64 *sb)
242 VIR_AUTOFREE(char *) newpath = NULL;
244 virMockStatInit();
246 if (virMockStatRedirect(path, &newpath) < 0)
247 abort();
248 fdebug("__xstat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
250 VIR_MOCK_STAT_HOOK;
252 return real___xstat64(ver, newpath ? newpath : path, sb);
254 #endif
256 #ifdef MOCK_LSTAT
258 lstat(const char *path, struct stat *sb)
260 VIR_AUTOFREE(char *) newpath = NULL;
262 virMockStatInit();
264 if (virMockStatRedirect(path, &newpath) < 0)
265 abort();
266 fdebug("lstat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
268 VIR_MOCK_STAT_HOOK;
270 return real_lstat(newpath ? newpath : path, sb);
272 #endif
274 #ifdef MOCK_LSTAT64
276 lstat64(const char *path, struct stat64 *sb)
278 VIR_AUTOFREE(char *) newpath = NULL;
280 virMockStatInit();
282 if (virMockStatRedirect(path, &newpath) < 0)
283 abort();
284 fdebug("lstat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
286 VIR_MOCK_STAT_HOOK;
288 return real_lstat64(newpath ? newpath : path, sb);
290 #endif
292 #ifdef MOCK___LXSTAT
294 __lxstat(int ver, const char *path, struct stat *sb)
296 VIR_AUTOFREE(char *) newpath = NULL;
298 virMockStatInit();
300 if (virMockStatRedirect(path, &newpath) < 0)
301 abort();
302 fdebug("__lxstat redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
304 VIR_MOCK_STAT_HOOK;
306 return real___lxstat(ver, newpath ? newpath : path, sb);
308 #endif
310 #ifdef MOCK___LXSTAT64
312 __lxstat64(int ver, const char *path, struct stat64 *sb)
314 VIR_AUTOFREE(char *) newpath = NULL;
316 virMockStatInit();
318 if (virMockStatRedirect(path, &newpath) < 0)
319 abort();
320 fdebug("__lxstat64 redirect %s to %s sb=%p\n", path, newpath ? newpath : path, sb);
322 VIR_MOCK_STAT_HOOK;
324 return real___lxstat64(ver, newpath ? newpath : path, sb);
326 #endif