diff options
author | Michal Privoznik <mprivozn@redhat.com> | 2016-04-18 14:10:33 +0200 |
---|---|---|
committer | Michal Privoznik <mprivozn@redhat.com> | 2016-05-14 09:46:23 +0200 |
commit | 6326865e6b9ac21e1569d51d414cb29913999442 (patch) | |
tree | 1fec94d22512d00a1c41f75982a0c9e1d6675685 /tests/virtestmock.c | |
parent | 47d2dc831ac94cc2eb9518b887e513233b063777 (diff) | |
download | libvirt-6326865e6b9ac21e1569d51d414cb29913999442.tar.gz |
virtestmock: Print invalid file accesses into a file
All the accesses to files outside our build or source directories
are now identified and appended into a file for later processing.
The location of the file that contains all the records can be
controlled via VIR_TEST_FILE_ACCESS env variable and defaults to
abs_builddir "/test_file_access.txt".
The script that will process the access file is to be added in
next commit.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Diffstat (limited to 'tests/virtestmock.c')
-rw-r--r-- | tests/virtestmock.c | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/tests/virtestmock.c b/tests/virtestmock.c index 0877956b02..59ca5e5b07 100644 --- a/tests/virtestmock.c +++ b/tests/virtestmock.c @@ -24,9 +24,14 @@ #include <unistd.h> #include <sys/types.h> #include <fcntl.h> +#include <execinfo.h> +#include <sys/file.h> #include "internal.h" #include "configmake.h" +#include "virstring.h" +#include "viralloc.h" +#include "virfile.h" static int (*real_open)(const char *path, int flags, ...); static FILE *(*real_fopen)(const char *path, const char *mode); @@ -36,6 +41,11 @@ static int (*real___xstat)(int ver, const char *path, struct stat *sb); static int (*real_lstat)(const char *path, struct stat *sb); static int (*real___lxstat)(int ver, const char *path, struct stat *sb); +static const char *progname; +const char *output; + +#define VIR_FILE_ACCESS_DEFAULT abs_builddir "/test_file_access.txt" + static void init_syms(void) { if (real_open) @@ -49,9 +59,90 @@ static void init_syms(void) } static void -checkPath(const char *path ATTRIBUTE_UNUSED) +printFile(const char *file) { - /* Nada */ + FILE *fp; + const char *testname = getenv("VIR_TEST_MOCK_TESTNAME"); + + if (!progname) { + progname = getenv("VIR_TEST_MOCK_PROGNAME"); + + if (!progname) + return; + + output = getenv("VIR_TEST_FILE_ACCESS_OUTPUT"); + if (!output) + output = VIR_FILE_ACCESS_DEFAULT; + } + + if (!(fp = real_fopen(output, "a"))) { + fprintf(stderr, "Unable to open %s: %s\n", output, strerror(errno)); + abort(); + } + + if (flock(fileno(fp), LOCK_EX) < 0) { + fprintf(stderr, "Unable to lock %s: %s\n", output, strerror(errno)); + fclose(fp); + abort(); + } + + /* Now append the following line into the output file: + * $file: $progname $testname */ + + fprintf(fp, "%s: %s", file, progname); + if (testname) + fprintf(fp, ": %s", testname); + + fputc('\n', fp); + + flock(fileno(fp), LOCK_UN); + fclose(fp); +} + +static void +checkPath(const char *path) +{ + char *fullPath = NULL; + char *relPath = NULL; + char *crippledPath = NULL; + + if (path[0] != '/' && + virAsprintfQuiet(&relPath, "./%s", path) < 0) + goto error; + + /* Le sigh. Both canonicalize_file_name() and realpath() + * expect @path to exist otherwise they return an error. So + * if we are called over an non-existent file, this could + * return an error. In that case do our best and hope we will + * catch possible error. */ + if ((fullPath = canonicalize_file_name(relPath ? relPath : path))) { + path = fullPath; + } else { + /* Yeah, our worst nightmares just became true. Path does + * not exist. Cut off the last component and retry. */ + if (VIR_STRDUP_QUIET(crippledPath, relPath ? relPath : path) < 0) + goto error; + + virFileRemoveLastComponent(crippledPath); + + if ((fullPath = canonicalize_file_name(crippledPath))) + path = fullPath; + } + + + if (!STRPREFIX(path, abs_topsrcdir) && + !STRPREFIX(path, abs_topbuilddir)) { + printFile(path); + } + + VIR_FREE(crippledPath); + VIR_FREE(relPath); + VIR_FREE(fullPath); + + return; + error: + fprintf(stderr, "Out of memory\n"); + abort(); } |