summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-01-23 17:35:58 +0100
committerStef Walter <stefw@gnome.org>2013-02-05 14:54:53 +0100
commit9a21e6ddf9eb7bb0f13f01cddba9dedd7a6e43b3 (patch)
tree2b30ed4e47685f088f2876010ed48cfa5bd65315
parent3e70ecbab850bcc08ee89e1256d82cca70d80ee7 (diff)
downloadp11-kit-9a21e6ddf9eb7bb0f13f01cddba9dedd7a6e43b3.tar.gz
Support for sane writing to files extracted
* Implement atomic writes of files * Writing with checks that not overwriting anything unless desired * Writing and overwriting of directory contents in a robust way
-rw-r--r--build/certs/Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--tools/Makefile.am3
-rw-r--r--tools/save.c462
-rw-r--r--tools/save.h79
-rw-r--r--tools/tests/Makefile.am52
-rw-r--r--tools/tests/files/cacert3.derbin0 -> 1885 bytes
-rw-r--r--tools/tests/test-save.c494
-rw-r--r--tools/tests/test.c200
-rw-r--r--tools/tests/test.h211
10 files changed, 1504 insertions, 0 deletions
diff --git a/build/certs/Makefile.am b/build/certs/Makefile.am
index a1a7017..a272c04 100644
--- a/build/certs/Makefile.am
+++ b/build/certs/Makefile.am
@@ -4,10 +4,12 @@
# distributed in the tarballs
TRUST = $(top_srcdir)/trust/tests
+TOOLS = $(top_srcdir)/tools/tests
prepare-certs:
cp -v cacert3.der $(TRUST)/anchors
cp -v cacert3.der $(TRUST)/files
+ cp -v cacert3.der $(TOOLS)/files
openssl x509 -in cacert3.der -inform DER -out $(TRUST)/files/cacert3.pem
openssl x509 -in cacert3.der -inform DER -out $(TRUST)/files/cacert3-trusted.pem \
-addtrust clientAuth -addtrust serverAuth -addreject emailProtection \
diff --git a/configure.ac b/configure.ac
index 63235fd..a6bb696 100644
--- a/configure.ac
+++ b/configure.ac
@@ -421,6 +421,7 @@ AC_CONFIG_FILES([Makefile
p11-kit/p11-kit-1.pc
p11-kit/pkcs11.conf.example
tools/Makefile
+ tools/tests/Makefile
trust/Makefile
trust/tests/Makefile
])
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 43adf56..fab1bd9 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,5 +1,7 @@
NULL =
+SUBDIRS = . tests
+
COMMON = $(top_srcdir)/common
INCLUDES = \
@@ -16,6 +18,7 @@ bin_PROGRAMS = \
p11_kit_SOURCES = \
list.c \
+ save.c save.h \
tool.c tool.h \
$(NULL)
diff --git a/tools/save.c b/tools/save.c
new file mode 100644
index 0000000..695c1fc
--- /dev/null
+++ b/tools/save.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2013, Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+
+#include "buffer.h"
+#include "debug.h"
+#include "dict.h"
+#include "library.h"
+#include "save.h"
+
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct _p11_save_file {
+ char *path;
+ char *temp;
+ int fd;
+ int flags;
+};
+
+struct _p11_save_dir {
+ p11_dict *cache;
+ char *path;
+ int flags;
+};
+
+bool
+p11_save_write_and_finish (p11_save_file *file,
+ const void *data,
+ size_t length)
+{
+ bool ret;
+
+ if (!file)
+ return false;
+
+ ret = p11_save_write (file, data, length);
+ if (!p11_save_finish_file (file, ret))
+ ret = false;
+
+ return ret;
+}
+
+p11_save_file *
+p11_save_open_file (const char *path,
+ int flags)
+{
+ struct stat st;
+ p11_save_file *file;
+ char *temp;
+ int fd;
+
+ return_val_if_fail (path != NULL, NULL);
+
+ /*
+ * This is just an early convenience check. We check again
+ * later when committing, in a non-racy fashion.
+ */
+
+ if (!(flags & P11_SAVE_OVERWRITE)) {
+ if (stat (path, &st) >= 0) {
+ p11_message ("file already exists: %s", path);
+ return NULL;
+ }
+ }
+
+ if (asprintf (&temp, "%s.XXXXXX", path) < 0)
+ return_val_if_reached (NULL);
+
+ fd = mkstemp (temp);
+ if (fd < 0) {
+ p11_message ("couldn't create file: %s: %s",
+ path, strerror (errno));
+ free (temp);
+ return NULL;
+ }
+
+ file = calloc (1, sizeof (p11_save_file));
+ return_val_if_fail (file != NULL, NULL);
+ file->temp = temp;
+ file->path = strdup (path);
+ return_val_if_fail (file->path != NULL, NULL);
+ file->flags = flags;
+ file->fd = fd;
+
+ return file;
+}
+
+bool
+p11_save_write (p11_save_file *file,
+ const void *data,
+ size_t length)
+{
+ const unsigned char *buf = data;
+ ssize_t written = 0;
+ ssize_t res;
+
+ if (!file)
+ return false;
+
+ while (written < length) {
+ res = write (file->fd, buf + written, length - written);
+ if (res <= 0) {
+ if (errno == EAGAIN && errno == EINTR)
+ continue;
+ p11_message ("couldn't write to file: %s: %s",
+ file->temp, strerror (errno));
+ return false;
+ } else {
+ written += res;
+ }
+ }
+
+ return true;
+}
+
+static void
+filo_free (p11_save_file *file)
+{
+ free (file->temp);
+ free (file->path);
+ free (file);
+}
+
+bool
+p11_save_finish_file (p11_save_file *file,
+ bool commit)
+{
+ bool ret = true;
+
+ if (!file)
+ return false;
+
+ if (!commit) {
+ unlink (file->temp);
+ close (file->fd);
+ filo_free (file);
+ return true;
+ }
+
+ /* Set the mode of the file */
+ if (chmod (file->temp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
+ p11_message ("couldn't set file permissions: %s: %s",
+ file->temp, strerror (errno));
+ close (file->fd);
+ ret = false;
+
+ } else if (close (file->fd) < 0) {
+ p11_message ("couldn't write file: %s: %s",
+ file->temp, strerror (errno));
+ ret = false;
+
+ /* Atomically rename the tempfile over the filename */
+ } else if (file->flags & P11_SAVE_OVERWRITE) {
+ if (rename (file->temp, file->path) < 0) {
+ p11_message ("couldn't complete writing file: %s: %s",
+ file->path, strerror (errno));
+ ret = false;
+ } else {
+ unlink (file->temp);
+ }
+
+ /* When not overwriting, link will fail if filename exists. */
+ } else {
+ if (link (file->temp, file->path) < 0) {
+ p11_message ("couldn't complete writing of file: %s: %s",
+ file->path, strerror (errno));
+ ret = false;
+ }
+ unlink (file->temp);
+ }
+
+ filo_free (file);
+ return ret;
+}
+
+p11_save_dir *
+p11_save_open_directory (const char *path,
+ int flags)
+{
+ mode_t mode = S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH;
+ p11_save_dir *dir;
+
+ return_val_if_fail (path != NULL, NULL);
+
+ if (mkdir (path, mode) < 0) {
+ if (!(flags & P11_SAVE_OVERWRITE) || errno != EEXIST) {
+ p11_message ("directory already exists: %s", path);
+ return NULL;
+ }
+ }
+
+ dir = calloc (1, sizeof (p11_save_dir));
+ return_val_if_fail (dir != NULL, NULL);
+
+ dir->path = strdup (path);
+ return_val_if_fail (dir->path != NULL, NULL);
+
+ dir->cache = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
+ return_val_if_fail (dir->cache != NULL, NULL);
+
+ dir->flags = flags;
+ return dir;
+}
+
+static char *
+make_unique_name (p11_save_dir *dir,
+ const char *filename,
+ const char *extension)
+{
+ char unique[16];
+ p11_buffer buf;
+ int i;
+
+ p11_buffer_init_null (&buf, 0);
+
+ for (i = 0; true; i++) {
+
+ p11_buffer_reset (&buf, 64);
+
+ switch (i) {
+
+ /*
+ * For the first iteration, just build the filename as
+ * provided by the caller.
+ */
+ case 0:
+ p11_buffer_add (&buf, filename, -1);
+ break;
+
+ /*
+ * On later iterations we try to add a numeric .N suffix
+ * before the extension, so the resulting file might look
+ * like filename.1.ext.
+ *
+ * As a special case if the extension is already '.0' then
+ * just just keep incerementing that.
+ */
+ case 1:
+ if (extension && strcmp (extension, ".0") == 0)
+ extension = NULL;
+ /* fall through */
+
+ default:
+ p11_buffer_add (&buf, filename, -1);
+ snprintf (unique, sizeof (unique), ".%d", i);
+ p11_buffer_add (&buf, unique, -1);
+ break;
+ }
+
+ if (extension)
+ p11_buffer_add (&buf, extension, -1);
+
+ return_val_if_fail (p11_buffer_ok (&buf), NULL);
+
+ if (!p11_dict_get (dir->cache, buf.data))
+ return p11_buffer_steal (&buf, NULL);
+ }
+
+ assert_not_reached ();
+}
+
+p11_save_file *
+p11_save_open_file_in (p11_save_dir *dir,
+ const char *basename,
+ const char *extension,
+ const char **ret_name)
+{
+ p11_save_file *file = NULL;
+ char *name;
+ char *path;
+
+ return_val_if_fail (dir != NULL, NULL);
+ return_val_if_fail (basename != NULL, NULL);
+
+ name = make_unique_name (dir, basename, extension);
+ return_val_if_fail (name != NULL, NULL);
+
+ if (asprintf (&path, "%s/%s", dir->path, name) < 0)
+ return_val_if_reached (NULL);
+
+ file = p11_save_open_file (path, dir->flags);
+
+ if (file) {
+ if (!p11_dict_set (dir->cache, name, name))
+ return_val_if_reached (NULL);
+ if (ret_name)
+ *ret_name = name;
+ name = NULL;
+ }
+
+ free (name);
+ free (path);
+
+ return file;
+}
+
+bool
+p11_save_symlink_in (p11_save_dir *dir,
+ const char *linkname,
+ const char *extension,
+ const char *destination)
+{
+ char *name;
+ char *path;
+ bool ret;
+
+ return_val_if_fail (dir != NULL, false);
+ return_val_if_fail (linkname != NULL, false);
+ return_val_if_fail (destination != NULL, false);
+
+ name = make_unique_name (dir, linkname, extension);
+ return_val_if_fail (name != NULL, false);
+
+ if (asprintf (&path, "%s/%s", dir->path, name) < 0)
+ return_val_if_reached (false);
+
+ unlink (path);
+
+ if (symlink (destination, path) < 0) {
+ p11_message ("couldn't create symlink: %s: %s",
+ path, strerror (errno));
+ ret = false;
+ } else {
+ if (!p11_dict_set (dir->cache, name, name))
+ return_val_if_reached (false);
+ name = NULL;
+ ret = true;
+ }
+
+ free (path);
+ free (name);
+
+ return ret;
+}
+
+static bool
+cleanup_directory (const char *directory,
+ p11_dict *cache)
+{
+ struct dirent *dp;
+ p11_dict *remove;
+ p11_dictiter iter;
+ char *path;
+ DIR *dir;
+ int skip;
+ bool ret;
+
+ /* First we load all the modules */
+ dir = opendir (directory);
+ if (!dir) {
+ p11_message ("couldn't list directory: %s: %s",
+ directory, strerror (errno));
+ return false;
+ }
+
+ remove = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
+
+ /* We're within a global mutex, so readdir is safe */
+ while ((dp = readdir (dir)) != NULL) {
+ if (p11_dict_get (cache, dp->d_name))
+ continue;
+
+ if (asprintf (&path, "%s/%s", directory, dp->d_name) < 0)
+ return_val_if_reached (false);
+
+#ifdef HAVE_STRUCT_DIRENT_D_TYPE
+ if(dp->d_type != DT_UNKNOWN) {
+ skip = (dp->d_type == DT_DIR);
+ } else
+#endif
+ {
+ struct stat st;
+
+ skip = (stat (path, &st) < 0) || S_ISDIR (st.st_mode);
+ }
+
+ if (!skip) {
+ if (!p11_dict_set (remove, path, path))
+ return_val_if_reached (false);
+ } else {
+ free (path);
+ }
+ }
+
+ closedir (dir);
+
+ ret = true;
+
+ /* Remove all the files still in the cache */
+ p11_dict_iterate (remove, &iter);
+ while (p11_dict_next (&iter, (void **)&path, NULL)) {
+ if (unlink (path) < 0 && errno != ENOENT) {
+ p11_message ("couldn't remove file: %s: %s",
+ path, strerror (errno));
+ ret = false;
+ break;
+ }
+ }
+
+ p11_dict_free (remove);
+
+ return ret;
+}
+
+bool
+p11_save_finish_directory (p11_save_dir *dir,
+ bool commit)
+{
+ bool ret = true;
+
+ if (!dir)
+ return false;
+
+ if (commit && (dir->flags & P11_SAVE_OVERWRITE))
+ ret = cleanup_directory (dir->path, dir->cache);
+
+ p11_dict_free (dir->cache);
+ free (dir->path);
+ free (dir);
+
+ return ret;
+}
diff --git a/tools/save.h b/tools/save.h
new file mode 100644
index 0000000..3e877ae
--- /dev/null
+++ b/tools/save.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#ifndef P11_SAVE_H_
+#define P11_SAVE_H_
+
+#include "compat.h"
+
+enum {
+ P11_SAVE_OVERWRITE = 1 << 0,
+};
+
+typedef struct _p11_save_file p11_save_file;
+typedef struct _p11_save_dir p11_save_dir;
+
+p11_save_file * p11_save_open_file (const char *path,
+ int flags);
+
+bool p11_save_write (p11_save_file *file,
+ const void *data,
+ size_t length);
+
+bool p11_save_write_and_finish (p11_save_file *file,
+ const void *data,
+ size_t length);
+
+bool p11_save_finish_file (p11_save_file *file,
+ bool commit);
+
+const char * p11_save_file_name (p11_save_file *file);
+
+p11_save_dir * p11_save_open_directory (const char *path,
+ int flags);
+
+p11_save_file * p11_save_open_file_in (p11_save_dir *directory,
+ const char *basename,
+ const char *extension,
+ const char **filename);
+
+bool p11_save_symlink_in (p11_save_dir *dir,
+ const char *linkname,
+ const char *extension,
+ const char *destination);
+
+bool p11_save_finish_directory (p11_save_dir *dir,
+ bool commit);
+
+#endif /* P11_SAVE_H_ */
diff --git a/tools/tests/Makefile.am b/tools/tests/Makefile.am
new file mode 100644
index 0000000..e4dd7ff
--- /dev/null
+++ b/tools/tests/Makefile.am
@@ -0,0 +1,52 @@
+
+include $(top_srcdir)/build/Makefile.tests
+
+NULL =
+
+EXTRA_DIST = files
+
+if WITH_ASN1
+
+COMMON = $(top_srcdir)/common
+TOOLS = $(top_srcdir)/tools
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/p11-kit \
+ -I$(srcdir)/.. \
+ -I$(COMMON) \
+ -DP11_KIT_FUTURE_UNSTABLE_API \
+ $(CUTEST_CFLAGS)
+
+LDADD = \
+ $(top_builddir)/p11-kit/libp11-kit.la \
+ $(top_builddir)/common/libp11-data.la \
+ $(top_builddir)/common/libp11-library.la \
+ $(top_builddir)/common/libp11-compat.la \
+ $(builddir)/libtestcommon.la \
+ $(LIBTASN1_LIBS) \
+ $(LTLIBINTL) \
+ $(CUTEST_LIBS) \
+ $(NULL)
+
+noinst_LTLIBRARIES = \
+ libtestcommon.la
+
+libtestcommon_la_SOURCES = \
+ test.c test.h
+
+CHECK_PROGS = \
+ test-save \
+ $(NULL)
+
+noinst_PROGRAMS = \
+ $(CHECK_PROGS)
+
+TESTS = $(CHECK_PROGS:=$(EXEEXT))
+
+test_save_SOURCES = \
+ test-save.c \
+ $(TOOLS)/save.c \
+ $(NULL)
+
+endif # WITH_ASN1
diff --git a/tools/tests/files/cacert3.der b/tools/tests/files/cacert3.der
new file mode 100644
index 0000000..56f8c88
--- /dev/null
+++ b/tools/tests/files/cacert3.der
Binary files differ
diff --git a/tools/tests/test-save.c b/tools/tests/test-save.c
new file mode 100644
index 0000000..743ba88
--- /dev/null
+++ b/tools/tests/test-save.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2013, Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include "attrs.h"
+#include "compat.h"
+#include "debug.h"
+#include "dict.h"
+#include "library.h"
+#include "save.h"
+#include "test.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+struct {
+ char *directory;
+} test;
+
+static void
+setup (CuTest *tc)
+{
+ test.directory = strdup ("/tmp/test-extract.XXXXXX");
+ if (!mkdtemp (test.directory))
+ CuFail (tc, "mkdtemp() failed");
+}
+
+static void
+teardown (CuTest *tc)
+{
+ if (rmdir (test.directory) < 0)
+ CuFail (tc, "rmdir() failed");
+ free (test.directory);
+}
+
+static void
+write_zero_file (CuTest *tc,
+ const char *directory,
+ const char *name)
+{
+ char *filename;
+ int res;
+ int fd;
+
+ if (asprintf (&filename, "%s/%s", directory, name) < 0)
+ CuFail (tc, "asprintf() failed");
+
+ fd = open (filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ CuAssertTrue (tc, fd != -1);
+ res = close (fd);
+ CuAssertTrue (tc, res >= 0);
+}
+
+static void
+test_file_write (CuTest *tc)
+{
+ p11_save_file *file;
+ char *filename;
+ bool ret;
+
+ setup (tc);
+
+ if (asprintf (&filename, "%s/%s", test.directory, "extract-file") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ file = p11_save_open_file (filename, 0);
+ CuAssertPtrNotNull (tc, file);
+
+ ret = p11_save_write_and_finish (file, test_cacert3_ca_der, sizeof (test_cacert3_ca_der));
+ CuAssertIntEquals (tc, true, ret);
+ free (filename);
+
+ test_check_file (tc, test.directory, "extract-file", SRCDIR "/files/cacert3.der");
+
+ teardown (tc);
+}
+
+static void
+test_file_exists (CuTest *tc)
+{
+ p11_save_file *file;
+ char *filename;
+
+ setup (tc);
+
+ if (asprintf (&filename, "%s/%s", test.directory, "extract-file") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ write_zero_file (tc, test.directory, "extract-file");
+
+ p11_message_quiet ();
+
+ file = p11_save_open_file (filename, 0);
+ CuAssertTrue (tc, file == NULL);
+
+ p11_message_loud ();
+
+ unlink (filename);
+ free (filename);
+ teardown (tc);
+}
+
+static void
+test_file_bad_directory (CuTest *tc)
+{
+ p11_save_file *file;
+ char *filename;
+
+ setup (tc);
+
+ if (asprintf (&filename, "/non-existent/%s/%s", test.directory, "extract-file") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ p11_message_quiet ();
+
+ file = p11_save_open_file (filename, 0);
+ CuAssertTrue (tc, file == NULL);
+
+ p11_message_loud ();
+
+ free (filename);
+ teardown (tc);
+}
+
+static void
+test_file_overwrite (CuTest *tc)
+{
+ p11_save_file *file;
+ char *filename;
+ bool ret;
+
+ setup (tc);
+
+ if (asprintf (&filename, "%s/%s", test.directory, "extract-file") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ write_zero_file (tc, test.directory, "extract-file");
+
+ file = p11_save_open_file (filename, P11_SAVE_OVERWRITE);
+ CuAssertPtrNotNull (tc, file);
+
+ ret = p11_save_write_and_finish (file, test_cacert3_ca_der, sizeof (test_cacert3_ca_der));
+ CuAssertIntEquals (tc, true, ret);
+ free (filename);
+
+ test_check_file (tc, test.directory, "extract-file", SRCDIR "/files/cacert3.der");
+
+ teardown (tc);
+}
+
+static void
+test_write_with_null (CuTest *tc)
+{
+ bool ret;
+
+ ret = p11_save_write (NULL, "test", 4);
+ CuAssertIntEquals (tc, false, ret);
+}
+
+static void
+test_write_and_finish_with_null (CuTest *tc)
+{
+ bool ret;
+
+ ret = p11_save_write_and_finish (NULL, "test", 4);
+ CuAssertIntEquals (tc, false, ret);
+}
+
+static void
+test_file_abort (CuTest *tc)
+{
+ struct stat st;
+ p11_save_file *file;
+ char *filename;
+ bool ret;
+
+ setup (tc);
+
+ if (asprintf (&filename, "%s/%s", test.directory, "extract-file") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ file = p11_save_open_file (filename, 0);
+ CuAssertPtrNotNull (tc, file);
+
+ ret = p11_save_finish_file (file, false);
+ CuAssertIntEquals (tc, true, ret);
+
+ if (stat (filename, &st) >= 0 || errno != ENOENT)
+ CuFail (tc, "file should not exist");
+
+ free (filename);
+
+ teardown (tc);
+}
+
+
+static void
+test_directory_empty (CuTest *tc)
+{
+ p11_save_dir *dir;
+ char *subdir;
+ bool ret;
+
+ setup (tc);
+
+ if (asprintf (&subdir, "%s/%s", test.directory, "extract-dir") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ dir = p11_save_open_directory (subdir, 0);
+ CuAssertPtrNotNull (tc, dir);
+
+ ret = p11_save_finish_directory (dir, true);
+ CuAssertIntEquals (tc, true, ret);
+
+ test_check_directory (tc, subdir, (NULL, NULL));
+
+ rmdir (subdir);
+ free (subdir);
+
+ teardown (tc);
+}
+
+static void
+test_directory_files (CuTest *tc)
+{
+ const char *filename;
+ p11_save_dir *dir;
+ char *subdir;
+ bool ret;
+
+ setup (tc);
+
+ if (asprintf (&subdir, "%s/%s", test.directory, "extract-dir") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ dir = p11_save_open_directory (subdir, 0);
+ CuAssertPtrNotNull (tc, dir);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "blah", ".cer", &filename),
+ test_cacert3_ca_der, sizeof (test_cacert3_ca_der));
+ CuAssertIntEquals (tc, true, ret);
+ CuAssertStrEquals (tc, "blah.cer", filename);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "file", ".txt", &filename),
+ test_text, strlen (test_text));
+ CuAssertIntEquals (tc, true, ret);
+ CuAssertStrEquals (tc, "file.txt", filename);
+
+ ret = p11_save_symlink_in (dir, "link", ".ext", "/the/destination");
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_finish_directory (dir, true);
+ CuAssertIntEquals (tc, true, ret);
+
+ test_check_directory (tc, subdir, ("blah.cer", "file.txt", "link.ext", NULL));
+ test_check_file (tc, subdir, "blah.cer", SRCDIR "/files/cacert3.der");
+ test_check_data (tc, subdir, "file.txt", test_text, strlen (test_text));
+ test_check_symlink (tc, subdir, "link.ext", "/the/destination");
+
+ rmdir (subdir);
+ free (subdir);
+
+ teardown (tc);
+}
+
+static void
+test_directory_dups (CuTest *tc)
+{
+ const char *filename;
+ p11_save_dir *dir;
+ char *subdir;
+ bool ret;
+
+ setup (tc);
+
+ if (asprintf (&subdir, "%s/%s", test.directory, "extract-dir") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ dir = p11_save_open_directory (subdir, 0);
+ CuAssertPtrNotNull (tc, dir);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "file", ".txt", &filename),
+ test_text, 5);
+ CuAssertIntEquals (tc, true, ret);
+ CuAssertStrEquals (tc, "file.txt", filename);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "file", ".txt", &filename),
+ test_text, 10);
+ CuAssertIntEquals (tc, true, ret);
+ CuAssertStrEquals (tc, "file.1.txt", filename);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "file", ".txt", NULL),
+ test_text, 15);
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "no-ext", NULL, NULL),
+ test_text, 8);
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "no-ext", NULL, NULL),
+ test_text, 16);
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "with-num", ".0", NULL),
+ test_text, 14);
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "with-num", ".0", NULL),
+ test_text, 15);
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_symlink_in (dir, "link", ".0", "/destination1");
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_symlink_in (dir, "link", ".0", "/destination2");
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_save_finish_directory (dir, true);
+ CuAssertIntEquals (tc, true, ret);
+
+ test_check_directory (tc, subdir, ("file.txt", "file.1.txt", "file.2.txt",
+ "no-ext", "no-ext.1",
+ "with-num.0", "with-num.1",
+ "link.0", "link.1",
+ NULL));
+ test_check_data (tc, subdir, "file.txt", test_text, 5);
+ test_check_data (tc, subdir, "file.1.txt", test_text, 10);
+ test_check_data (tc, subdir, "file.2.txt", test_text, 15);
+ test_check_data (tc, subdir, "no-ext", test_text, 8);
+ test_check_data (tc, subdir, "no-ext.1", test_text, 16);
+ test_check_data (tc, subdir, "with-num.0", test_text, 14);
+ test_check_data (tc, subdir, "with-num.1", test_text, 15);
+ test_check_symlink (tc, subdir, "link.0", "/destination1");
+ test_check_symlink (tc, subdir, "link.1", "/destination2");
+
+ rmdir (subdir);
+ free (subdir);
+
+ teardown (tc);
+}
+
+static void
+test_directory_exists (CuTest *tc)
+{
+ p11_save_dir *dir;
+ char *subdir;
+
+ setup (tc);
+
+ if (asprintf (&subdir, "%s/%s", test.directory, "extract-dir") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ if (mkdir (subdir, S_IRWXU) < 0)
+ CuFail (tc, "mkdir() failed");
+
+ p11_message_quiet ();
+
+ dir = p11_save_open_directory (subdir, 0);
+ CuAssertPtrEquals (tc, NULL, dir);
+
+ p11_message_loud ();
+
+ rmdir (subdir);
+ free (subdir);
+
+ teardown (tc);
+}
+
+static void
+test_directory_overwrite (CuTest *tc)
+{
+ const char *filename;
+ p11_save_dir *dir;
+ char *subdir;
+ bool ret;
+
+ setup (tc);
+
+ if (asprintf (&subdir, "%s/%s", test.directory, "extract-dir") < 0)
+ CuFail (tc, "asprintf() failed");
+
+ if (mkdir (subdir, S_IRWXU) < 0)
+ CuFail (tc, "mkdir() failed");
+
+ /* Some initial files into this directory, which get overwritten */
+ write_zero_file (tc, subdir, "file.txt");
+ write_zero_file (tc, subdir, "another-file");
+ write_zero_file (tc, subdir, "third-file");
+
+ dir = p11_save_open_directory (subdir, P11_SAVE_OVERWRITE);
+ CuAssertPtrNotNull (tc, dir);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "blah", ".cer", &filename),
+ test_cacert3_ca_der, sizeof (test_cacert3_ca_der));
+ CuAssertIntEquals (tc, true, ret);
+ CuAssertStrEquals (tc, "blah.cer", filename);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "file", ".txt", &filename),
+ test_text, strlen (test_text));
+ CuAssertIntEquals (tc, true, ret);
+ CuAssertStrEquals (tc, "file.txt", filename);
+
+ ret = p11_save_write_and_finish (p11_save_open_file_in (dir, "file", ".txt", &filename),
+ test_text, 10);
+ CuAssertIntEquals (tc, true, ret);
+ CuAssertStrEquals (tc, "file.1.txt", filename);
+
+ ret = p11_save_finish_directory (dir, true);
+ CuAssertIntEquals (tc, true, ret);
+
+ test_check_directory (tc, subdir, ("blah.cer", "file.txt", "file.1.txt", NULL));
+ test_check_data (tc, subdir, "blah.cer", test_cacert3_ca_der, sizeof (test_cacert3_ca_der));
+ test_check_data (tc, subdir, "file.txt", test_text, strlen (test_text));
+ test_check_data (tc, subdir, "file.1.txt", test_text, 10);
+
+ rmdir (subdir);
+ free (subdir);
+
+ teardown (tc);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ SUITE_ADD_TEST (suite, test_file_write);
+ SUITE_ADD_TEST (suite, test_file_exists);
+ SUITE_ADD_TEST (suite, test_file_bad_directory);
+ SUITE_ADD_TEST (suite, test_file_overwrite);
+ SUITE_ADD_TEST (suite, test_write_with_null);
+ SUITE_ADD_TEST (suite, test_write_and_finish_with_null);
+ SUITE_ADD_TEST (suite, test_file_abort);
+
+ SUITE_ADD_TEST (suite, test_directory_empty);
+ SUITE_ADD_TEST (suite, test_directory_files);
+ SUITE_ADD_TEST (suite, test_directory_dups);
+ SUITE_ADD_TEST (suite, test_directory_exists);
+ SUITE_ADD_TEST (suite, test_directory_overwrite);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
diff --git a/tools/tests/test.c b/tools/tests/test.c
new file mode 100644
index 0000000..ecc0410
--- /dev/null
+++ b/tools/tests/test.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2013, Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include "debug.h"
+#include "test.h"
+
+#include <assert.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static char *
+read_file (CuTest *tc,
+ const char *file,
+ int line,
+ const char *filename,
+ long *len)
+{
+ FILE *f = NULL;
+ char *data;
+
+ f = fopen (filename, "r");
+ if (f == NULL)
+ CuFail_Line (tc, file, line, "Couldn't open file", filename);
+
+ /* Figure out size */
+ if (fseek (f, 0, SEEK_END) == -1 ||
+ (*len = ftell (f)) == -1 ||
+ fseek (f, 0, SEEK_SET) == -1) {
+ CuFail_Line (tc, file, line, "Couldn't get file length", filename);
+ }
+
+ data = malloc (*len ? *len : 1);
+ assert (data != NULL);
+
+ /* And read in one block */
+ if (fread (data, 1, *len, f) != *len)
+ CuFail_Line (tc, file, line, "Couldn't read file", filename);
+
+ fclose (f);
+
+ return data;
+}
+
+void
+test_check_file_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ const char *name,
+ const char *reference)
+{
+ char *refdata;
+ long reflen;
+
+ refdata = read_file (tc, file, line, reference, &reflen);
+ test_check_data_msg (tc, file, line, directory, name, refdata, reflen);
+ free (refdata);
+}
+
+void
+test_check_data_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ const char *name,
+ const void *refdata,
+ long reflen)
+{
+ char *filedata;
+ char *filename;
+ long filelen;
+
+ if (asprintf (&filename, "%s/%s", directory, name) < 0)
+ CuFail_Line (tc, file, line, "asprintf() failed", NULL);
+
+ filedata = read_file (tc, file, line, filename, &filelen);
+
+ if (filelen != reflen || memcmp (filedata, refdata, reflen) != 0)
+ CuFail_Line (tc, file, line, "File contents not as expected", filename);
+
+ unlink (filename);
+ free (filename);
+ free (filedata);
+}
+
+void
+test_check_symlink_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ const char *name,
+ const char *destination)
+{
+ char buf[1024] = { 0, };
+ char *filename;
+
+ if (asprintf (&filename, "%s/%s", directory, name) < 0)
+ CuFail_Line (tc, file, line, "asprintf() failed", NULL);
+
+ if (readlink (filename, buf, sizeof (buf)) < 0)
+ CuFail_Line (tc, file, line, "Couldn't read symlink", filename);
+
+ CuAssertStrEquals_LineMsg (tc, file, line, "symlink contents wrong", destination, buf);
+
+ unlink (filename);
+ free (filename);
+}
+
+p11_dict *
+test_check_directory_files (const char *file,
+ ...)
+{
+ p11_dict *files;
+ va_list va;
+
+ files = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL);
+
+ va_start (va, file);
+
+ while (file != NULL) {
+ if (!p11_dict_set (files, (void *)file, (void *)file))
+ return_val_if_reached (NULL);
+ file = va_arg (va, const char *);
+ }
+
+ va_end (va);
+
+ return files;
+}
+
+void
+test_check_directory_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ p11_dict *files)
+{
+ p11_dictiter iter;
+ struct dirent *dp;
+ const char *name;
+ DIR *dir;
+
+ dir = opendir (directory);
+ if (dir == NULL)
+ CuFail_Line (tc, file ,line, "Couldn't open directory", directory);
+
+ while ((dp = readdir (dir)) != NULL) {
+ if (strcmp (dp->d_name, ".") == 0 ||
+ strcmp (dp->d_name, "..") == 0)
+ continue;
+
+ if (!p11_dict_remove (files, dp->d_name))
+ CuFail_Line (tc, file, line, "Unexpected file in directory", dp->d_name);
+ }
+
+ closedir (dir);
+
+ p11_dict_iterate (files, &iter);
+ while (p11_dict_next (&iter, (void **)&name, NULL))
+ CuFail_Line (tc, file, line, "Couldn't find file in directory", name);
+
+ p11_dict_free (files);
+}
diff --git a/tools/tests/test.h b/tools/tests/test.h
new file mode 100644
index 0000000..c3e0d08
--- /dev/null
+++ b/tools/tests/test.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2013, Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#ifndef TEST_COMMON_H_
+#define TEST_COMMON_H_
+
+#include "CuTest.h"
+
+#include "dict.h"
+
+#include <stdlib.h>
+
+static const char test_text[] = "This is the file text";
+
+static const unsigned char test_cacert3_ca_der[] = {
+ 0x30, 0x82, 0x07, 0x59, 0x30, 0x82, 0x05, 0x41, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x0a,
+ 0x41, 0x8a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
+ 0x00, 0x30, 0x79, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x52, 0x6f,
+ 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x61, 0x63, 0x65, 0x72,
+ 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19,
+ 0x43, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20,
+ 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72,
+ 0x74, 0x40, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x31, 0x30, 0x35, 0x32, 0x33, 0x31, 0x37, 0x34, 0x38, 0x30, 0x32, 0x5a, 0x17, 0x0d, 0x32,
+ 0x31, 0x30, 0x35, 0x32, 0x30, 0x31, 0x37, 0x34, 0x38, 0x30, 0x32, 0x5a, 0x30, 0x54, 0x31, 0x14,
+ 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x20,
+ 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74,
+ 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x43,
+ 0x41, 0x63, 0x65, 0x72, 0x74, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x52, 0x6f,
+ 0x6f, 0x74, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82,
+ 0x02, 0x01, 0x00, 0xab, 0x49, 0x35, 0x11, 0x48, 0x7c, 0xd2, 0x26, 0x7e, 0x53, 0x94, 0xcf, 0x43,
+ 0xa9, 0xdd, 0x28, 0xd7, 0x42, 0x2a, 0x8b, 0xf3, 0x87, 0x78, 0x19, 0x58, 0x7c, 0x0f, 0x9e, 0xda,
+ 0x89, 0x7d, 0xe1, 0xfb, 0xeb, 0x72, 0x90, 0x0d, 0x74, 0xa1, 0x96, 0x64, 0xab, 0x9f, 0xa0, 0x24,
+ 0x99, 0x73, 0xda, 0xe2, 0x55, 0x76, 0xc7, 0x17, 0x7b, 0xf5, 0x04, 0xac, 0x46, 0xb8, 0xc3, 0xbe,
+ 0x7f, 0x64, 0x8d, 0x10, 0x6c, 0x24, 0xf3, 0x61, 0x9c, 0xc0, 0xf2, 0x90, 0xfa, 0x51, 0xe6, 0xf5,
+ 0x69, 0x01, 0x63, 0xc3, 0x0f, 0x56, 0xe2, 0x4a, 0x42, 0xcf, 0xe2, 0x44, 0x8c, 0x25, 0x28, 0xa8,
+ 0xc5, 0x79, 0x09, 0x7d, 0x46, 0xb9, 0x8a, 0xf3, 0xe9, 0xf3, 0x34, 0x29, 0x08, 0x45, 0xe4, 0x1c,
+ 0x9f, 0xcb, 0x94, 0x04, 0x1c, 0x81, 0xa8, 0x14, 0xb3, 0x98, 0x65, 0xc4, 0x43, 0xec, 0x4e, 0x82,
+ 0x8d, 0x09, 0xd1, 0xbd, 0xaa, 0x5b, 0x8d, 0x92, 0xd0, 0xec, 0xde, 0x90, 0xc5, 0x7f, 0x0a, 0xc2,
+ 0xe3, 0xeb, 0xe6, 0x31, 0x5a, 0x5e, 0x74, 0x3e, 0x97, 0x33, 0x59, 0xe8, 0xc3, 0x03, 0x3d, 0x60,
+ 0x33, 0xbf, 0xf7, 0xd1, 0x6f, 0x47, 0xc4, 0xcd, 0xee, 0x62, 0x83, 0x52, 0x6e, 0x2e, 0x08, 0x9a,
+ 0xa4, 0xd9, 0x15, 0x18, 0x91, 0xa6, 0x85, 0x92, 0x47, 0xb0, 0xae, 0x48, 0xeb, 0x6d, 0xb7, 0x21,
+ 0xec, 0x85, 0x1a, 0x68, 0x72, 0x35, 0xab, 0xff, 0xf0, 0x10, 0x5d, 0xc0, 0xf4, 0x94, 0xa7, 0x6a,
+ 0xd5, 0x3b, 0x92, 0x7e, 0x4c, 0x90, 0x05, 0x7e, 0x93, 0xc1, 0x2c, 0x8b, 0xa4, 0x8e, 0x62, 0x74,
+ 0x15, 0x71, 0x6e, 0x0b, 0x71, 0x03, 0xea, 0xaf, 0x15, 0x38, 0x9a, 0xd4, 0xd2, 0x05, 0x72, 0x6f,
+ 0x8c, 0xf9, 0x2b, 0xeb, 0x5a, 0x72, 0x25, 0xf9, 0x39, 0x46, 0xe3, 0x72, 0x1b, 0x3e, 0x04, 0xc3,
+ 0x64, 0x27, 0x22, 0x10, 0x2a, 0x8a, 0x4f, 0x58, 0xa7, 0x03, 0xad, 0xbe, 0xb4, 0x2e, 0x13, 0xed,
+ 0x5d, 0xaa, 0x48, 0xd7, 0xd5, 0x7d, 0xd4, 0x2a, 0x7b, 0x5c, 0xfa, 0x46, 0x04, 0x50, 0xe4, 0xcc,
+ 0x0e, 0x42, 0x5b, 0x8c, 0xed, 0xdb, 0xf2, 0xcf, 0xfc, 0x96, 0x93, 0xe0, 0xdb, 0x11, 0x36, 0x54,
+ 0x62, 0x34, 0x38, 0x8f, 0x0c, 0x60, 0x9b, 0x3b, 0x97, 0x56, 0x38, 0xad, 0xf3, 0xd2, 0x5b, 0x8b,
+ 0xa0, 0x5b, 0xea, 0x4e, 0x96, 0xb8, 0x7c, 0xd7, 0xd5, 0xa0, 0x86, 0x70, 0x40, 0xd3, 0x91, 0x29,
+ 0xb7, 0xa2, 0x3c, 0xad, 0xf5, 0x8c, 0xbb, 0xcf, 0x1a, 0x92, 0x8a, 0xe4, 0x34, 0x7b, 0xc0, 0xd8,
+ 0x6c, 0x5f, 0xe9, 0x0a, 0xc2, 0xc3, 0xa7, 0x20, 0x9a, 0x5a, 0xdf, 0x2c, 0x5d, 0x52, 0x5c, 0xba,
+ 0x47, 0xd5, 0x9b, 0xef, 0x24, 0x28, 0x70, 0x38, 0x20, 0x2f, 0xd5, 0x7f, 0x29, 0xc0, 0xb2, 0x41,
+ 0x03, 0x68, 0x92, 0xcc, 0xe0, 0x9c, 0xcc, 0x97, 0x4b, 0x45, 0xef, 0x3a, 0x10, 0x0a, 0xab, 0x70,
+ 0x3a, 0x98, 0x95, 0x70, 0xad, 0x35, 0xb1, 0xea, 0x85, 0x2b, 0xa4, 0x1c, 0x80, 0x21, 0x31, 0xa9,
+ 0xae, 0x60, 0x7a, 0x80, 0x26, 0x48, 0x00, 0xb8, 0x01, 0xc0, 0x93, 0x63, 0x55, 0x22, 0x91, 0x3c,
+ 0x56, 0xe7, 0xaf, 0xdb, 0x3a, 0x25, 0xf3, 0x8f, 0x31, 0x54, 0xea, 0x26, 0x8b, 0x81, 0x59, 0xf9,
+ 0xa1, 0xd1, 0x53, 0x11, 0xc5, 0x7b, 0x9d, 0x03, 0xf6, 0x74, 0x11, 0xe0, 0x6d, 0xb1, 0x2c, 0x3f,
+ 0x2c, 0x86, 0x91, 0x99, 0x71, 0x9a, 0xa6, 0x77, 0x8b, 0x34, 0x60, 0xd1, 0x14, 0xb4, 0x2c, 0xac,
+ 0x9d, 0xaf, 0x8c, 0x10, 0xd3, 0x9f, 0xc4, 0x6a, 0xf8, 0x6f, 0x13, 0xfc, 0x73, 0x59, 0xf7, 0x66,
+ 0x42, 0x74, 0x1e, 0x8a, 0xe3, 0xf8, 0xdc, 0xd2, 0x6f, 0x98, 0x9c, 0xcb, 0x47, 0x98, 0x95, 0x40,
+ 0x05, 0xfb, 0xe9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0x0d, 0x30, 0x82, 0x02, 0x09,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0xa8, 0x71, 0x60, 0x4c,
+ 0x88, 0x13, 0xf0, 0x78, 0xd9, 0x89, 0x77, 0xb5, 0x6d, 0xc5, 0x89, 0xdf, 0xbc, 0xb1, 0x7a, 0x30,
+ 0x81, 0xa3, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0x9b, 0x30, 0x81, 0x98, 0x80, 0x14, 0x16,
+ 0xb5, 0x32, 0x1b, 0xd4, 0xc7, 0xf3, 0xe0, 0xe6, 0x8e, 0xf3, 0xbd, 0xd2, 0xb0, 0x3a, 0xee, 0xb2,
+ 0x39, 0x18, 0xd1, 0xa1, 0x7d, 0xa4, 0x7b, 0x30, 0x79, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x07, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06,
+ 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+ 0x2e, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x69,
+ 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12,
+ 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x40, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f,
+ 0x72, 0x67, 0x82, 0x01, 0x00, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
+ 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x5d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x04, 0x51, 0x30, 0x4f, 0x30, 0x23, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e,
+ 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x30, 0x28, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x63,
+ 0x61, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x4a, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x43, 0x30, 0x41,
+ 0x30, 0x3f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x90, 0x4a, 0x30, 0x33, 0x30, 0x31,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x25, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x70, 0x68, 0x70, 0x3f, 0x69, 0x64, 0x3d, 0x31,
+ 0x30, 0x30, 0x34, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x27,
+ 0x16, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43, 0x41, 0x63,
+ 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x70, 0x68,
+ 0x70, 0x3f, 0x69, 0x64, 0x3d, 0x31, 0x30, 0x30, 0x50, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86,
+ 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x43, 0x16, 0x41, 0x54, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x79,
+ 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x46, 0x52, 0x45, 0x45, 0x2c, 0x20, 0x67, 0x6f,
+ 0x20, 0x74, 0x6f, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x43,
+ 0x41, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x29, 0x28, 0x85,
+ 0xae, 0x44, 0xa9, 0xb9, 0xaf, 0xa4, 0x79, 0x13, 0xf0, 0xa8, 0xa3, 0x2b, 0x97, 0x60, 0xf3, 0x5c,
+ 0xee, 0xe3, 0x2f, 0xc1, 0xf6, 0xe2, 0x66, 0xa0, 0x11, 0xae, 0x36, 0x37, 0x3a, 0x76, 0x15, 0x04,
+ 0x53, 0xea, 0x42, 0xf5, 0xf9, 0xea, 0xc0, 0x15, 0xd8, 0xa6, 0x82, 0xd9, 0xe4, 0x61, 0xae, 0x72,
+ 0x0b, 0x29, 0x5c, 0x90, 0x43, 0xe8, 0x41, 0xb2, 0xe1, 0x77, 0xdb, 0x02, 0x13, 0x44, 0x78, 0x47,
+ 0x55, 0xaf, 0x58, 0xfc, 0xcc, 0x98, 0xf6, 0x45, 0xb9, 0xd1, 0x20, 0xf8, 0xd8, 0x21, 0x07, 0xfe,
+ 0x6d, 0xaa, 0x73, 0xd4, 0xb3, 0xc6, 0x07, 0xe9, 0x09, 0x85, 0xcc, 0x3b, 0xf2, 0xb6, 0xbe, 0x2c,
+ 0x1c, 0x25, 0xd5, 0x71, 0x8c, 0x39, 0xb5, 0x2e, 0xea, 0xbe, 0x18, 0x81, 0xba, 0xb0, 0x93, 0xb8,
+ 0x0f, 0xe3, 0xe6, 0xd7, 0x26, 0x8c, 0x31, 0x5a, 0x72, 0x03, 0x84, 0x52, 0xe6, 0xa6, 0xf5, 0x33,
+ 0x22, 0x45, 0x0a, 0xc8, 0x0b, 0x0d, 0x8a, 0xb8, 0x36, 0x6f, 0x90, 0x09, 0xa1, 0xab, 0xbd, 0xd7,
+ 0xd5, 0x4e, 0x2e, 0x71, 0xa2, 0xd4, 0xae, 0xfa, 0xa7, 0x54, 0x2b, 0xeb, 0x35, 0x8d, 0x5a, 0xb7,
+ 0x54, 0x88, 0x2f, 0xee, 0x74, 0x9f, 0xed, 0x48, 0x16, 0xca, 0x0d, 0x48, 0xd0, 0x94, 0xd3, 0xac,
+ 0xa4, 0xa2, 0xf6, 0x24, 0xdf, 0x92, 0xe3, 0xbd, 0xeb, 0x43, 0x40, 0x91, 0x6e, 0x1c, 0x18, 0x8e,
+ 0x56, 0xb4, 0x82, 0x12, 0xf3, 0xa9, 0x93, 0x9f, 0xd4, 0xbc, 0x9c, 0xad, 0x9c, 0x75, 0xee, 0x5a,
+ 0x97, 0x1b, 0x95, 0xe7, 0x74, 0x2d, 0x1c, 0x0f, 0xb0, 0x2c, 0x97, 0x9f, 0xfb, 0xa9, 0x33, 0x39,
+ 0x7a, 0xe7, 0x03, 0x3a, 0x92, 0x8e, 0x22, 0xf6, 0x8c, 0x0d, 0xe4, 0xd9, 0x7e, 0x0d, 0x76, 0x18,
+ 0xf7, 0x01, 0xf9, 0xef, 0x96, 0x96, 0xa2, 0x55, 0x73, 0xc0, 0x3c, 0x71, 0xb4, 0x1d, 0x1a, 0x56,
+ 0x43, 0xb7, 0xc3, 0x0a, 0x8d, 0x72, 0xfc, 0xe2, 0x10, 0x09, 0x0b, 0x41, 0xce, 0x8c, 0x94, 0xa0,
+ 0xf9, 0x03, 0xfd, 0x71, 0x73, 0x4b, 0x8a, 0x57, 0x33, 0xe5, 0x8e, 0x74, 0x7e, 0x15, 0x01, 0x00,
+ 0xe6, 0xcc, 0x4a, 0x1c, 0xe7, 0x7f, 0x95, 0x19, 0x2d, 0xc5, 0xa5, 0x0c, 0x8b, 0xbb, 0xb5, 0xed,
+ 0x85, 0xb3, 0x5c, 0xd3, 0xdf, 0xb8, 0xb9, 0xf2, 0xca, 0xc7, 0x0d, 0x01, 0x14, 0xac, 0x70, 0x58,
+ 0xc5, 0x8c, 0x8d, 0x33, 0xd4, 0x9d, 0x66, 0xa3, 0x1a, 0x50, 0x95, 0x23, 0xfc, 0x48, 0xe0, 0x06,
+ 0x43, 0x12, 0xd9, 0xcd, 0xa7, 0x86, 0x39, 0x2f, 0x36, 0x72, 0xa3, 0x80, 0x10, 0xe4, 0xe1, 0xf3,
+ 0xd1, 0xcb, 0x5b, 0x1a, 0xc0, 0xe4, 0x80, 0x9a, 0x7c, 0x13, 0x73, 0x06, 0x4f, 0xdb, 0xa3, 0x6b,
+ 0x24, 0x0a, 0xba, 0xb3, 0x1c, 0xbc, 0x4a, 0x78, 0xbb, 0xe5, 0xe3, 0x75, 0x38, 0xa5, 0x48, 0xa7,
+ 0xa2, 0x1e, 0xaf, 0x76, 0xd4, 0x5e, 0xf7, 0x38, 0x86, 0x56, 0x5a, 0x89, 0xce, 0xd6, 0xc3, 0xa7,
+ 0x79, 0xb2, 0x52, 0xa0, 0xc6, 0xf1, 0x85, 0xb4, 0x25, 0x8c, 0xf2, 0x3f, 0x96, 0xb3, 0x10, 0xd9,
+ 0x8d, 0x6c, 0x57, 0x3b, 0x9f, 0x6f, 0x86, 0x3a, 0x18, 0x82, 0x22, 0x36, 0xc8, 0xb0, 0x91, 0x38,
+ 0xdb, 0x2a, 0xa1, 0x93, 0xaa, 0x84, 0x3f, 0xf5, 0x27, 0x65, 0xae, 0x73, 0xd5, 0xc8, 0xd5, 0xd3,
+ 0x77, 0xea, 0x4b, 0x9d, 0xc7, 0x41, 0xbb, 0xc7, 0xc0, 0xe3, 0xa0, 0x3f, 0xe4, 0x7d, 0xa4, 0x8d,
+ 0x73, 0xe6, 0x12, 0x4b, 0xdf, 0xa1, 0x73, 0x73, 0x73, 0x3a, 0x80, 0xe8, 0xd5, 0xcb, 0x8e, 0x2f,
+ 0xcb, 0xea, 0x13, 0xa7, 0xd6, 0x41, 0x8b, 0xac, 0xfa, 0x3c, 0x89, 0xd7, 0x24, 0xf5, 0x4e, 0xb4,
+ 0xe0, 0x61, 0x92, 0xb7, 0xf3, 0x37, 0x98, 0xc4, 0xbe, 0x96, 0xa3, 0xb7, 0x8a,
+};
+
+void test_check_file_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ const char *filename,
+ const char *reference);
+
+void test_check_data_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ const char *filename,
+ const void *refdata,
+ long reflen);
+
+void test_check_symlink_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ const char *name,
+ const char *destination);
+
+p11_dict * test_check_directory_files (const char *file,
+ ...) GNUC_NULL_TERMINATED;
+
+void test_check_directory_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const char *directory,
+ p11_dict *files);
+
+#define test_check_file(tc, directory, name, reference) \
+ (test_check_file_msg (tc, __FILE__, __LINE__, directory, name, reference))
+
+#define test_check_data(tc, directory, name, data, length) \
+ (test_check_data_msg (tc, __FILE__, __LINE__, directory, name, data, length))
+
+#define test_check_symlink(tc, directory, name, destination) \
+ (test_check_symlink_msg (tc, __FILE__, __LINE__, directory, name, destination))
+
+#define test_check_directory(tc, directory, files) \
+ (test_check_directory_msg (tc, __FILE__, __LINE__, directory, \
+ test_check_directory_files files))
+
+#endif /* TEST_COMMON_H_ */