diff --git a/cfg.mk b/cfg.mk index c0aba5781d..c19f615f9a 100644 --- a/cfg.mk +++ b/cfg.mk @@ -1296,3 +1296,6 @@ exclude_file_name_regexp--sc_prohibit_not_strneq = \ exclude_file_name_regexp--sc_prohibit_dt_without_code = \ ^docs/(newapi\.xsl|(apps|contact)\.html\.in)$$ + +exclude_file_name_regexp--sc_prohibit_always-defined_macros = \ + ^tests/virtestmock.c$$ diff --git a/configure.ac b/configure.ac index 10fbd20e65..74c33b3483 100644 --- a/configure.ac +++ b/configure.ac @@ -332,6 +332,7 @@ AC_CHECK_HEADERS([pwd.h regex.h sys/un.h \ libtasn1.h sys/ucred.h sys/mount.h]) dnl Check whether endian provides handy macros. AC_CHECK_DECLS([htole64], [], [], [[#include ]]) +AC_CHECK_FUNCS([stat stat64 __xstat __xstat64 lstat lstat64 __lxstat __lxstat64]) dnl We need to decide at configure time if libvirt will use real atomic dnl operations ("lock free") or emulated ones with a mutex. diff --git a/tests/virtestmock.c b/tests/virtestmock.c index 54669ba6af..688945d805 100644 --- a/tests/virtestmock.c +++ b/tests/virtestmock.c @@ -34,13 +34,33 @@ #include "viralloc.h" #include "virfile.h" +/* stat can be a macro as follows: + * + * #define stat stat64 + * + * This wouldn't fly with our mock. Make sure that the macro (and + * all its friends) are undefined. We don't want anybody mangling + * our code. */ +#undef stat +#undef stat64 +#undef __xstat +#undef __xstat64 +#undef lstat +#undef lstat64 +#undef __lxstat +#undef __lxstat64 + static int (*real_open)(const char *path, int flags, ...); static FILE *(*real_fopen)(const char *path, const char *mode); static int (*real_access)(const char *path, int mode); static int (*real_stat)(const char *path, struct stat *sb); +static int (*real_stat64)(const char *path, void *sb); static int (*real___xstat)(int ver, const char *path, struct stat *sb); +static int (*real___xstat64)(int ver, const char *path, void *sb); static int (*real_lstat)(const char *path, struct stat *sb); +static int (*real_lstat64)(const char *path, void *sb); static int (*real___lxstat)(int ver, const char *path, struct stat *sb); +static int (*real___lxstat64)(int ver, const char *path, void *sb); static const char *progname; const char *output; @@ -56,7 +76,9 @@ static void init_syms(void) VIR_MOCK_REAL_INIT(fopen); VIR_MOCK_REAL_INIT(access); VIR_MOCK_REAL_INIT_ALT(stat, __xstat); + VIR_MOCK_REAL_INIT_ALT(stat64, __xstat64); VIR_MOCK_REAL_INIT_ALT(lstat, __lxstat); + VIR_MOCK_REAL_INIT_ALT(lstat64, __lxstat64); } static void @@ -187,6 +209,27 @@ int access(const char *path, int mode) return real_access(path, mode); } +/* Okay, the following ifdef rain forest may look messy at a + * first glance. But here's the thing: during run time linking of + * a binary, stat() may not be acutally needing symbol stat. It + * might as well not had been stat() in the first place (see the + * reasoning at the beginning of this file). However, if we would + * expose stat symbol here, we will poison the well and trick + * dynamic linker into thinking we are some old binary that still + * uses the symbol. So whenever code from upper layers calls + * stat(), the control would get here, but real_stat can actually + * be a NULL pointer because newer glibc have __xstat instead. + * Worse, it can have __xstat64 instead __xstat. + * + * Anyway, these ifdefs are there to implement the following + * preference function: + * + * stat < stat64 < __xstat < __xstat64 + * + * It's the same story with lstat. + * Also, I feel sorry for you that you had to read this. + */ +#if defined(HAVE_STAT) && !defined(HAVE___XSTAT) int stat(const char *path, struct stat *sb) { init_syms(); @@ -195,7 +238,20 @@ int stat(const char *path, struct stat *sb) return real_stat(path, sb); } +#endif +#if defined(HAVE_STAT64) && !defined(HAVE___XSTAT64) +int stat64(const char *path, struct stat64 *sb) +{ + init_syms(); + + checkPath(path); + + return real_stat64(path, sb); +} +#endif + +#if defined(HAVE___XSTAT) && !defined(HAVE___XSTAT64) int __xstat(int ver, const char *path, struct stat *sb) { @@ -205,7 +261,21 @@ __xstat(int ver, const char *path, struct stat *sb) return real___xstat(ver, path, sb); } +#endif +#if defined(HAVE___XSTAT64) +int +__xstat64(int ver, const char *path, struct stat64 *sb) +{ + init_syms(); + + checkPath(path); + + return real___xstat64(ver, path, sb); +} +#endif + +#if defined(HAVE_LSTAT) && !defined(HAVE___LXSTAT) int lstat(const char *path, struct stat *sb) { @@ -215,7 +285,21 @@ lstat(const char *path, struct stat *sb) return real_lstat(path, sb); } +#endif +#if defined(HAVE_LSTAT64) && !defined(HAVE___LXSTAT64) +int +lstat64(const char *path, struct stat64 *sb) +{ + init_syms(); + + checkPath(path); + + return real_lstat64(path, sb); +} +#endif + +#if defined(HAVE___LXSTAT) && !defined(HAVE___LXSTAT64) int __lxstat(int ver, const char *path, struct stat *sb) { @@ -225,3 +309,16 @@ __lxstat(int ver, const char *path, struct stat *sb) return real___lxstat(ver, path, sb); } +#endif + +#if defined(HAVE___LXSTAT64) +int +__lxstat64(int ver, const char *path, struct stat64 *sb) +{ + init_syms(); + + checkPath(path); + + return real___lxstat64(ver, path, sb); +} +#endif