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/>.
23 #include <sys/types.h>
28 #include <sys/socket.h>
34 #include "configmake.h"
35 #include "virstring.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
;
47 #define VIR_FILE_ACCESS_DEFAULT abs_builddir "/test_file_access.txt"
49 static void init_syms(void)
54 VIR_MOCK_REAL_INIT(open
);
55 VIR_MOCK_REAL_INIT(fopen
);
56 VIR_MOCK_REAL_INIT(access
);
57 VIR_MOCK_REAL_INIT(connect
);
61 printFile(const char *file
,
65 const char *testname
= getenv("VIR_TEST_MOCK_TESTNAME");
68 progname
= getenv("VIR_TEST_MOCK_PROGNAME");
73 output
= getenv("VIR_TEST_FILE_ACCESS_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
));
83 if (flock(fileno(fp
), LOCK_EX
) < 0) {
84 fprintf(stderr
, "Unable to lock %s: %s\n", output
, strerror(errno
));
89 /* Now append the following line into the output file:
90 * $file: $progname: $func: $testname */
92 fprintf(fp
, "%s: %s: %s", file
, func
, progname
);
94 fprintf(fp
, ": %s", testname
);
98 flock(fileno(fp
), LOCK_UN
);
102 #define CHECK_PATH(path) \
103 checkPath(path, __FUNCTION__)
106 checkPath(const char *path
,
109 char *fullPath
= NULL
;
110 char *relPath
= NULL
;
111 char *crippledPath
= NULL
;
113 if (path
[0] != '/' &&
114 virAsprintfQuiet(&relPath
, "./%s", path
) < 0)
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
))) {
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)
129 virFileRemoveLastComponent(crippledPath
);
131 if ((fullPath
= virFileCanonicalizePath(crippledPath
)))
136 if (!STRPREFIX(path
, abs_top_srcdir
) &&
137 !STRPREFIX(path
, abs_top_builddir
)) {
138 printFile(path
, func
);
141 VIR_FREE(crippledPath
);
147 fprintf(stderr
, "Out of memory\n");
152 int open(const char *path
, int flags
, ...)
160 if (flags
& O_CREAT
) {
164 mode
= (mode_t
) va_arg(ap
, int);
166 ret
= real_open(path
, flags
, mode
);
168 ret
= real_open(path
, flags
);
173 FILE *fopen(const char *path
, const char *mode
)
179 return real_fopen(path
, mode
);
183 int access(const char *path
, int mode
)
189 return real_access(path
, mode
);
193 #define VIR_MOCK_STAT_HOOK \
196 checkPath(path, "stat"); \
199 #include "virmockstathelpers.c"
201 static int virMockStatRedirect(const char *path ATTRIBUTE_UNUSED
, char **newpath ATTRIBUTE_UNUSED
)
207 int connect(int sockfd
, const struct sockaddr
*addr
, socklen_t addrlen
)
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
);
219 return real_connect(sockfd
, addr
, addrlen
);