backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / virtestmock.c
blobdf8cac64411a1910b60a727b295db631b641d8ae
1 /*
2 * Copyright (C) 2016 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/>.
19 #include <config.h>
21 #include "virmock.h"
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <fcntl.h>
25 #include <execinfo.h>
26 #include <sys/file.h>
27 #include <sys/stat.h>
28 #include <sys/socket.h>
29 #ifdef HAVE_SYS_UN_H
30 # include <sys/un.h>
31 #endif
33 #include "internal.h"
34 #include "configmake.h"
35 #include "virstring.h"
36 #include "viralloc.h"
37 #include "virfile.h"
39 static int (*real_open)(const char *path, int flags, ...);
40 static FILE *(*real_fopen)(const char *path, const char *mode);
41 static int (*real_access)(const char *path, int mode);
42 static int (*real_connect)(int fd, const struct sockaddr *addr, socklen_t addrlen);
44 static const char *progname;
45 const char *output;
47 #define VIR_FILE_ACCESS_DEFAULT abs_builddir "/test_file_access.txt"
49 static void init_syms(void)
51 if (real_open)
52 return;
54 VIR_MOCK_REAL_INIT(open);
55 VIR_MOCK_REAL_INIT(fopen);
56 VIR_MOCK_REAL_INIT(access);
57 VIR_MOCK_REAL_INIT(connect);
60 static void
61 printFile(const char *file,
62 const char *func)
64 FILE *fp;
65 const char *testname = getenv("VIR_TEST_MOCK_TESTNAME");
67 if (!progname) {
68 progname = getenv("VIR_TEST_MOCK_PROGNAME");
70 if (!progname)
71 return;
73 output = getenv("VIR_TEST_FILE_ACCESS_OUTPUT");
74 if (!output)
75 output = VIR_FILE_ACCESS_DEFAULT;
78 if (!(fp = real_fopen(output, "a"))) {
79 fprintf(stderr, "Unable to open %s: %s\n", output, strerror(errno));
80 abort();
83 if (flock(fileno(fp), LOCK_EX) < 0) {
84 fprintf(stderr, "Unable to lock %s: %s\n", output, strerror(errno));
85 fclose(fp);
86 abort();
89 /* Now append the following line into the output file:
90 * $file: $progname: $func: $testname */
92 fprintf(fp, "%s: %s: %s", file, func, progname);
93 if (testname)
94 fprintf(fp, ": %s", testname);
96 fputc('\n', fp);
98 flock(fileno(fp), LOCK_UN);
99 fclose(fp);
102 #define CHECK_PATH(path) \
103 checkPath(path, __FUNCTION__)
105 static void
106 checkPath(const char *path,
107 const char *func)
109 char *fullPath = NULL;
110 char *relPath = NULL;
111 char *crippledPath = NULL;
113 if (path[0] != '/' &&
114 virAsprintfQuiet(&relPath, "./%s", path) < 0)
115 goto error;
117 /* Le sigh. virFileCanonicalizePath() expects @path to exist, otherwise
118 * it will return an error. So if we are called over an non-existent
119 * file, this could return an error. In that case do our best and hope
120 * we will catch possible errors. */
121 if ((fullPath = virFileCanonicalizePath(relPath ? relPath : path))) {
122 path = fullPath;
123 } else {
124 /* Yeah, our worst nightmares just became true. Path does
125 * not exist. Cut off the last component and retry. */
126 if (VIR_STRDUP_QUIET(crippledPath, relPath ? relPath : path) < 0)
127 goto error;
129 virFileRemoveLastComponent(crippledPath);
131 if ((fullPath = virFileCanonicalizePath(crippledPath)))
132 path = fullPath;
136 if (!STRPREFIX(path, abs_top_srcdir) &&
137 !STRPREFIX(path, abs_top_builddir)) {
138 printFile(path, func);
141 VIR_FREE(crippledPath);
142 VIR_FREE(relPath);
143 VIR_FREE(fullPath);
145 return;
146 error:
147 fprintf(stderr, "Out of memory\n");
148 abort();
152 int open(const char *path, int flags, ...)
154 int ret;
156 init_syms();
158 CHECK_PATH(path);
160 if (flags & O_CREAT) {
161 va_list ap;
162 mode_t mode;
163 va_start(ap, flags);
164 mode = (mode_t) va_arg(ap, int);
165 va_end(ap);
166 ret = real_open(path, flags, mode);
167 } else {
168 ret = real_open(path, flags);
170 return ret;
173 FILE *fopen(const char *path, const char *mode)
175 init_syms();
177 CHECK_PATH(path);
179 return real_fopen(path, mode);
183 int access(const char *path, int mode)
185 init_syms();
187 CHECK_PATH(path);
189 return real_access(path, mode);
193 #define VIR_MOCK_STAT_HOOK \
194 do { \
195 init_syms(); \
196 checkPath(path, "stat"); \
197 } while (0)
199 #include "virmockstathelpers.c"
201 static int virMockStatRedirect(const char *path ATTRIBUTE_UNUSED, char **newpath ATTRIBUTE_UNUSED)
203 return 0;
207 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
209 init_syms();
211 #ifdef HAVE_SYS_UN_H
212 if (addrlen == sizeof(struct sockaddr_un)) {
213 struct sockaddr_un *tmp = (struct sockaddr_un *) addr;
214 if (tmp->sun_family == AF_UNIX)
215 CHECK_PATH(tmp->sun_path);
217 #endif
219 return real_connect(sockfd, addr, addrlen);