|
|
2c83a8 |
From f9ff58e8cde1d3b6f5eb5307e2019d54c5e28487 Mon Sep 17 00:00:00 2001
|
|
|
2c83a8 |
From: Matej Habrnal <mhabrnal@redhat.com>
|
|
|
2c83a8 |
Date: Thu, 11 Feb 2016 17:29:50 +0100
|
|
|
2c83a8 |
Subject: [PATCH] dd: add a function for compressing dumpdirs
|
|
|
2c83a8 |
|
|
|
2c83a8 |
Introduce dd_create_archive() function.
|
|
|
2c83a8 |
|
|
|
2c83a8 |
I added the argument 'flags' in order to avoid the need to introduce
|
|
|
2c83a8 |
dd_create_archive_ext() function in the future. I am sure will use this
|
|
|
2c83a8 |
flag in the future (e.g. Encrypted).
|
|
|
2c83a8 |
|
|
|
2c83a8 |
Signed-off-by: Jakub Filak <jfilak@redhat.com>
|
|
|
2c83a8 |
Signed-off-by: Matej Habrnal <mhabrnal@redhat.com>
|
|
|
2c83a8 |
---
|
|
|
2c83a8 |
po/POTFILES.in | 1 +
|
|
|
2c83a8 |
src/include/dump_dir.h | 26 +++++
|
|
|
2c83a8 |
src/lib/Makefile.am | 1 +
|
|
|
2c83a8 |
src/lib/dump_dir.c | 117 ++++++++++++++++++++
|
|
|
2c83a8 |
src/plugins/Makefile.am | 2 -
|
|
|
2c83a8 |
tests/dump_dir.at | 275 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
2c83a8 |
6 files changed, 420 insertions(+), 2 deletions(-)
|
|
|
2c83a8 |
|
|
|
2c83a8 |
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
|
|
2c83a8 |
index 00046e2..30c9cb5 100644
|
|
|
2c83a8 |
--- a/po/POTFILES.in
|
|
|
2c83a8 |
+++ b/po/POTFILES.in
|
|
|
2c83a8 |
@@ -18,6 +18,7 @@ src/lib/abrt_sock.c
|
|
|
2c83a8 |
src/lib/client.c
|
|
|
2c83a8 |
src/lib/create_dump_dir.c
|
|
|
2c83a8 |
src/lib/curl.c
|
|
|
2c83a8 |
+src/lib/dump_dir.c
|
|
|
2c83a8 |
src/lib/event_config.c
|
|
|
2c83a8 |
src/lib/ureport.c
|
|
|
2c83a8 |
src/lib/make_descr.c
|
|
|
2c83a8 |
diff --git a/src/include/dump_dir.h b/src/include/dump_dir.h
|
|
|
2c83a8 |
index 07b119a..092ddeb 100644
|
|
|
2c83a8 |
--- a/src/include/dump_dir.h
|
|
|
2c83a8 |
+++ b/src/include/dump_dir.h
|
|
|
2c83a8 |
@@ -21,6 +21,9 @@
|
|
|
2c83a8 |
#ifndef LIBREPORT_DUMP_DIR_H_
|
|
|
2c83a8 |
#define LIBREPORT_DUMP_DIR_H_
|
|
|
2c83a8 |
|
|
|
2c83a8 |
+/* For const_string_vector_const_ptr_t */
|
|
|
2c83a8 |
+#include "libreport_types.h"
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
/* For DIR */
|
|
|
2c83a8 |
#include <sys/types.h>
|
|
|
2c83a8 |
#include <dirent.h>
|
|
|
2c83a8 |
@@ -178,6 +181,29 @@ int fdump_dir_stat_for_uid(int dir_fd, uid_t uid);
|
|
|
2c83a8 |
*/
|
|
|
2c83a8 |
int dd_mark_as_notreportable(struct dump_dir *dd, const char *reason);
|
|
|
2c83a8 |
|
|
|
2c83a8 |
+/* Creates a new archive from the dump directory contents
|
|
|
2c83a8 |
+ *
|
|
|
2c83a8 |
+ * The dd argument must be opened for reading.
|
|
|
2c83a8 |
+ *
|
|
|
2c83a8 |
+ * The archive_name must not exist. The file will be created with 0600 mode.
|
|
|
2c83a8 |
+ *
|
|
|
2c83a8 |
+ * The archive type is deduced from archive_name suffix. The supported archive
|
|
|
2c83a8 |
+ * suffixes are the following:
|
|
|
2c83a8 |
+ * - '.tag.gz' (note: the implementation uses child gzip process)
|
|
|
2c83a8 |
+ *
|
|
|
2c83a8 |
+ * The archive will include only the files that are not in the exclude_elements
|
|
|
2c83a8 |
+ * list. See get_global_always_excluded_elements().
|
|
|
2c83a8 |
+ *
|
|
|
2c83a8 |
+ * The argument "flags" is currently unused.
|
|
|
2c83a8 |
+ *
|
|
|
2c83a8 |
+ * @return 0 on success; otherwise non-0 value. -ENOSYS if archive type is not
|
|
|
2c83a8 |
+ * supported. -EEXIST if the archive file already exists. -ECHILD if child
|
|
|
2c83a8 |
+ * process fails. Other negative values can be converted to errno values by
|
|
|
2c83a8 |
+ * turning them positive.
|
|
|
2c83a8 |
+ */
|
|
|
2c83a8 |
+int dd_create_archive(struct dump_dir *dd, const char *archive_name,
|
|
|
2c83a8 |
+ const_string_vector_const_ptr_t exclude_elements, int flags);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
#ifdef __cplusplus
|
|
|
2c83a8 |
}
|
|
|
2c83a8 |
#endif
|
|
|
2c83a8 |
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
|
|
|
2c83a8 |
index f9ea602..50142f7 100644
|
|
|
2c83a8 |
--- a/src/lib/Makefile.am
|
|
|
2c83a8 |
+++ b/src/lib/Makefile.am
|
|
|
2c83a8 |
@@ -79,6 +79,7 @@ libreport_la_CPPFLAGS = \
|
|
|
2c83a8 |
$(AUGEAS_CFLAGS) \
|
|
|
2c83a8 |
-D_GNU_SOURCE
|
|
|
2c83a8 |
libreport_la_LDFLAGS = \
|
|
|
2c83a8 |
+ -ltar \
|
|
|
2c83a8 |
-version-info 0:1:0
|
|
|
2c83a8 |
libreport_la_LIBADD = \
|
|
|
2c83a8 |
$(JSON_C_LIBS) \
|
|
|
2c83a8 |
diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c
|
|
|
2c83a8 |
index 9096853..a5cd93e 100644
|
|
|
2c83a8 |
--- a/src/lib/dump_dir.c
|
|
|
2c83a8 |
+++ b/src/lib/dump_dir.c
|
|
|
2c83a8 |
@@ -17,6 +17,7 @@
|
|
|
2c83a8 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
2c83a8 |
*/
|
|
|
2c83a8 |
#include <sys/utsname.h>
|
|
|
2c83a8 |
+#include <libtar.h>
|
|
|
2c83a8 |
#include "internal_libreport.h"
|
|
|
2c83a8 |
|
|
|
2c83a8 |
// Locking logic:
|
|
|
2c83a8 |
@@ -1475,3 +1476,119 @@ int dd_mark_as_notreportable(struct dump_dir *dd, const char *reason)
|
|
|
2c83a8 |
dd_save_text(dd, FILENAME_NOT_REPORTABLE, reason);
|
|
|
2c83a8 |
return 0;
|
|
|
2c83a8 |
}
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+/* flags - for future needs */
|
|
|
2c83a8 |
+int dd_create_archive(struct dump_dir *dd, const char *archive_name,
|
|
|
2c83a8 |
+ const_string_vector_const_ptr_t exclude_elements, int flags)
|
|
|
2c83a8 |
+{
|
|
|
2c83a8 |
+ if (suffixcmp(archive_name, ".tar.gz") != 0)
|
|
|
2c83a8 |
+ return -ENOSYS;
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ int result = 0;
|
|
|
2c83a8 |
+ pid_t child;
|
|
|
2c83a8 |
+ TAR* tar = NULL;
|
|
|
2c83a8 |
+ int pipe_from_parent_to_child[2];
|
|
|
2c83a8 |
+ xpipe(pipe_from_parent_to_child);
|
|
|
2c83a8 |
+ child = fork();
|
|
|
2c83a8 |
+ if (child < 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ result = -errno;
|
|
|
2c83a8 |
+ /* Don't die, let the caller to execute his clean-up code. */
|
|
|
2c83a8 |
+ perror_msg("vfork");
|
|
|
2c83a8 |
+ return result;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+ if (child == 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ /* child */
|
|
|
2c83a8 |
+ close(pipe_from_parent_to_child[1]);
|
|
|
2c83a8 |
+ xmove_fd(pipe_from_parent_to_child[0], 0);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ int fd = open(archive_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
|
|
2c83a8 |
+ if (fd < 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ /* This r might interfer with exit status of gzip, but it is
|
|
|
2c83a8 |
+ * very unlikely (man 1 gzip):
|
|
|
2c83a8 |
+ * Exit status is normally 0; if an error occurs, exit status is
|
|
|
2c83a8 |
+ * 1. If a warning occurs, exit status is 2.
|
|
|
2c83a8 |
+ */
|
|
|
2c83a8 |
+ result = errno == EEXIST ? 100 : 3;
|
|
|
2c83a8 |
+ perror_msg("Can't open '%s'", archive_name);
|
|
|
2c83a8 |
+ exit(result);
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ xmove_fd(fd, 1);
|
|
|
2c83a8 |
+ execlp("gzip", "gzip", NULL);
|
|
|
2c83a8 |
+ perror_msg_and_die("Can't execute '%s'", "gzip");
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+ close(pipe_from_parent_to_child[0]);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* If child died (say, in xopen), then parent might get SIGPIPE.
|
|
|
2c83a8 |
+ * We want to properly unlock dd, therefore we must not die on SIGPIPE:
|
|
|
2c83a8 |
+ */
|
|
|
2c83a8 |
+ sighandler_t old_handler = signal(SIGPIPE, SIG_IGN);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* Create tar writer object */
|
|
|
2c83a8 |
+ if (tar_fdopen(&tar, pipe_from_parent_to_child[1], (char *)archive_name,
|
|
|
2c83a8 |
+ /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ result = -errno;
|
|
|
2c83a8 |
+ log_warning(_("Failed to open TAR writer"));
|
|
|
2c83a8 |
+ goto finito;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* Write data to the tarball */
|
|
|
2c83a8 |
+ dd_init_next_file(dd);
|
|
|
2c83a8 |
+ char *short_name, *full_name;
|
|
|
2c83a8 |
+ while (dd_get_next_file(dd, &short_name, &full_name))
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ if (!(exclude_elements && is_in_string_list(short_name, exclude_elements)))
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ if (tar_append_file(tar, full_name, short_name))
|
|
|
2c83a8 |
+ result = -errno;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ free(short_name);
|
|
|
2c83a8 |
+ free(full_name);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (result != 0)
|
|
|
2c83a8 |
+ goto finito;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* Close tar writer... */
|
|
|
2c83a8 |
+ if (tar_append_eof(tar) != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ result = -errno;
|
|
|
2c83a8 |
+ log_warning(_("Failed to finalize TAR archive"));
|
|
|
2c83a8 |
+ goto finito;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+finito:
|
|
|
2c83a8 |
+ signal(SIGPIPE, old_handler);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (tar != NULL && tar_close(tar) != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ result = -errno;
|
|
|
2c83a8 |
+ log_warning(_("Failed to close TAR writer"));
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* ...and check that gzip child finished successfully */
|
|
|
2c83a8 |
+ int status;
|
|
|
2c83a8 |
+ safe_waitpid(child, &status, 0);
|
|
|
2c83a8 |
+ if (status != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ result = -ECHILD;
|
|
|
2c83a8 |
+ if (WIFSIGNALED(status))
|
|
|
2c83a8 |
+ log_warning(_("gzip killed with signal %d"), WTERMSIG(status));
|
|
|
2c83a8 |
+ else if (WIFEXITED(status))
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ if (WEXITSTATUS(status) == 100)
|
|
|
2c83a8 |
+ result = -EEXIST;
|
|
|
2c83a8 |
+ else
|
|
|
2c83a8 |
+ log_warning(_("gzip exited with %d"), WEXITSTATUS(status));
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+ else
|
|
|
2c83a8 |
+ log_warning(_("gzip process failed"));
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ return result;
|
|
|
2c83a8 |
+}
|
|
|
2c83a8 |
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
|
|
|
2c83a8 |
index 7ec08d7..d5d75b6 100644
|
|
|
2c83a8 |
--- a/src/plugins/Makefile.am
|
|
|
2c83a8 |
+++ b/src/plugins/Makefile.am
|
|
|
2c83a8 |
@@ -145,7 +145,6 @@ reporter_rhtsupport_CPPFLAGS = \
|
|
|
2c83a8 |
$(LIBREPORT_CFLAGS) \
|
|
|
2c83a8 |
$(LIBXML_CFLAGS) \
|
|
|
2c83a8 |
-D_GNU_SOURCE
|
|
|
2c83a8 |
-reporter_rhtsupport_LDFLAGS = -ltar
|
|
|
2c83a8 |
reporter_rhtsupport_LDADD = \
|
|
|
2c83a8 |
$(GLIB_LIBS) \
|
|
|
2c83a8 |
$(LIBXML_LIBS) \
|
|
|
2c83a8 |
@@ -168,7 +167,6 @@ reporter_upload_CPPFLAGS = \
|
|
|
2c83a8 |
$(CURL_CFLAGS) \
|
|
|
2c83a8 |
$(LIBREPORT_CFLAGS) \
|
|
|
2c83a8 |
-D_GNU_SOURCE
|
|
|
2c83a8 |
-reporter_upload_LDFLAGS = -ltar
|
|
|
2c83a8 |
reporter_upload_LDADD = \
|
|
|
2c83a8 |
$(GLIB_LIBS) \
|
|
|
2c83a8 |
../lib/libreport-web.la \
|
|
|
2c83a8 |
diff --git a/tests/dump_dir.at b/tests/dump_dir.at
|
|
|
2c83a8 |
index a579243..fb8c7ce 100644
|
|
|
2c83a8 |
--- a/tests/dump_dir.at
|
|
|
2c83a8 |
+++ b/tests/dump_dir.at
|
|
|
2c83a8 |
@@ -47,3 +47,278 @@ int main(void)
|
|
|
2c83a8 |
return 0;
|
|
|
2c83a8 |
}
|
|
|
2c83a8 |
]])
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+## ----------------- ##
|
|
|
2c83a8 |
+## dd_create_archive ##
|
|
|
2c83a8 |
+## ----------------- ##
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+AT_TESTFUN([dd_create_archive],
|
|
|
2c83a8 |
+[[
|
|
|
2c83a8 |
+#include "internal_libreport.h"
|
|
|
2c83a8 |
+#include <libtar.h>
|
|
|
2c83a8 |
+#include <assert.h>
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+void verify_archive(struct dump_dir *dd, const char *file_name,
|
|
|
2c83a8 |
+ const_string_vector_const_ptr_t included_files,
|
|
|
2c83a8 |
+ const_string_vector_const_ptr_t excluded_files)
|
|
|
2c83a8 |
+{
|
|
|
2c83a8 |
+ unsigned c = 0;
|
|
|
2c83a8 |
+ for (const_string_vector_const_ptr_t i = included_files; i && *i; ++i)
|
|
|
2c83a8 |
+ ++c;
|
|
|
2c83a8 |
+ int *check_array = xzalloc(c * sizeof(int));
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ int pipe_from_parent_to_child[2];
|
|
|
2c83a8 |
+ xpipe(pipe_from_parent_to_child);
|
|
|
2c83a8 |
+ pid_t child = fork();
|
|
|
2c83a8 |
+ if (child < 0)
|
|
|
2c83a8 |
+ perror_msg_and_die("vfork");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (child == 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ /* child */
|
|
|
2c83a8 |
+ close(pipe_from_parent_to_child[0]);
|
|
|
2c83a8 |
+ xmove_fd(xopen(file_name, O_RDONLY), 0);
|
|
|
2c83a8 |
+ xmove_fd(pipe_from_parent_to_child[1], 1);
|
|
|
2c83a8 |
+ execlp("gzip", "gzip", "-d", NULL);
|
|
|
2c83a8 |
+ perror_msg_and_die("Can't execute '%s'", "gzip");
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+ close(pipe_from_parent_to_child[1]);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* If child died (say, in xopen), then parent might get SIGPIPE.
|
|
|
2c83a8 |
+ * We want to properly unlock dd, therefore we must not die on SIGPIPE:
|
|
|
2c83a8 |
+ */
|
|
|
2c83a8 |
+ signal(SIGPIPE, SIG_IGN);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ TAR* tar = NULL;
|
|
|
2c83a8 |
+ /* Create tar writer object */
|
|
|
2c83a8 |
+ if (tar_fdopen(&tar, pipe_from_parent_to_child[0], (char *)file_name,
|
|
|
2c83a8 |
+ /*fileops:(standard)*/ NULL, O_RDONLY, 0644, TAR_GNU) != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "Failed to open the pipe to gzip for archive: '%s'\n", file_name);
|
|
|
2c83a8 |
+ abort();
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ int r = 0;
|
|
|
2c83a8 |
+ const char *real_file = "/tmp/libreport-attest-extracted";
|
|
|
2c83a8 |
+ while ((r = th_read(tar)) == 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ char *path = th_get_pathname(tar);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (!TH_ISREG(tar))
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "Not regular file: '%s', found in archive: '%s'\n", path, file_name);
|
|
|
2c83a8 |
+ continue;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ const_string_vector_const_ptr_t i = included_files;
|
|
|
2c83a8 |
+ for (c = 0; i && *i; ++i, ++c)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ if (strcmp(*i, path) == 0)
|
|
|
2c83a8 |
+ break;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (i && *i != NULL)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ printf("Included file: '%s', found in archive '%s'\n", path, file_name);
|
|
|
2c83a8 |
+ check_array[c] += 1;
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ unlink(real_file);
|
|
|
2c83a8 |
+ if(tar_extract_regfile(tar, xstrdup(real_file)) != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "TAR failed to extract '%s' to '%s': %s\n", path, real_file, strerror(errno));
|
|
|
2c83a8 |
+ abort();
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ char *original = dd_load_text(dd, path);
|
|
|
2c83a8 |
+ assert(original != NULL);
|
|
|
2c83a8 |
+ assert(original[0] != '\0');
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ char *extracted = xmalloc_xopen_read_close("/tmp/libreport-attest-extracted", NULL);
|
|
|
2c83a8 |
+ assert(extracted != NULL);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (strcmp(extracted, original) != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "Invalid file contents: '%s'\nExp: '%s'\nGot: '%s'\n", path, original, extracted);
|
|
|
2c83a8 |
+ abort();
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ free(original);
|
|
|
2c83a8 |
+ free(extracted);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ continue;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ i = excluded_files;
|
|
|
2c83a8 |
+ for (; i && *i; ++i)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ if (strcmp(*i, path) == 0)
|
|
|
2c83a8 |
+ break;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (i && *i != NULL)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "Excluded file: '%s', found in archive '%s'\n", path, file_name);
|
|
|
2c83a8 |
+ abort();
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ fprintf(stderr, "Uncategorized file: '%s', found in archive '%s'\n", path, file_name);
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (r != 1)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "th_read() failed: %s\n", strerror(errno));
|
|
|
2c83a8 |
+ abort();
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ tar_close(tar);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ int status;
|
|
|
2c83a8 |
+ safe_waitpid(child, &status, 0);
|
|
|
2c83a8 |
+ if (status != 0)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "gzip status code '%d'\n", status);
|
|
|
2c83a8 |
+ abort();
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ int err = 0;
|
|
|
2c83a8 |
+ const_string_vector_const_ptr_t i = included_files;
|
|
|
2c83a8 |
+ for (c = 0; i && *i; ++i, ++c)
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ switch (check_array[c])
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ case 0:
|
|
|
2c83a8 |
+ fprintf(stderr, "Not found included file: '%s', in archive: %s\n", *i, file_name);
|
|
|
2c83a8 |
+ ++err;
|
|
|
2c83a8 |
+ break;
|
|
|
2c83a8 |
+ case 1:
|
|
|
2c83a8 |
+ fprintf(stdout, "Found included file: '%s', in archive: %s\n", *i, file_name);
|
|
|
2c83a8 |
+ break;
|
|
|
2c83a8 |
+ default:
|
|
|
2c83a8 |
+ fprintf(stderr, "%d occurrences of included file: '%s', in archive: %s\n", check_array[c], *i, file_name);
|
|
|
2c83a8 |
+ ++err;
|
|
|
2c83a8 |
+ break;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (err)
|
|
|
2c83a8 |
+ abort();
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ return;
|
|
|
2c83a8 |
+}
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+int main(void)
|
|
|
2c83a8 |
+{
|
|
|
2c83a8 |
+ g_verbose = 3;
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ char template[] = "/tmp/XXXXXX";
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ if (mkdtemp(template) == NULL) {
|
|
|
2c83a8 |
+ perror("mkdtemp()");
|
|
|
2c83a8 |
+ return EXIT_FAILURE;
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ printf("Dump dir path: %s\n", template);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ struct dump_dir *dd = dd_create(template, (uid_t)-1, 0640);
|
|
|
2c83a8 |
+ assert(dd != NULL || !"Cannot create new dump directory");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+#define COMMON_FILES "time", "last_occurrence", "uid", "kernel", \
|
|
|
2c83a8 |
+ "architecture", "hostname", "os_info", "os_release", \
|
|
|
2c83a8 |
+ "type", "count", "component", "program_log"
|
|
|
2c83a8 |
+#define SENSITIVE_FILES "environ", "backtrace", "secret_file", "private_file", \
|
|
|
2c83a8 |
+ "useless_file"
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ dd_create_basic_files(dd, geteuid(), NULL);
|
|
|
2c83a8 |
+ dd_save_text(dd, FILENAME_TYPE, "attest");
|
|
|
2c83a8 |
+ dd_save_text(dd, FILENAME_COUNT, "1");
|
|
|
2c83a8 |
+ dd_save_text(dd, FILENAME_COMPONENT, "libreport-attest");
|
|
|
2c83a8 |
+ dd_save_text(dd, "program_log", "Something very important!");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ const gchar *excluded_files[] = {
|
|
|
2c83a8 |
+ SENSITIVE_FILES,
|
|
|
2c83a8 |
+ NULL,
|
|
|
2c83a8 |
+ };
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ for (const gchar **iter = excluded_files; *iter; ++iter)
|
|
|
2c83a8 |
+ dd_save_text(dd, *iter, *iter);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* Un-supported archive type */
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "TEST-CASE: Un-supported type\n");
|
|
|
2c83a8 |
+ fprintf(stdout, "TEST-CASE: Un-supported type\n");
|
|
|
2c83a8 |
+ const int r = dd_create_archive(dd, "/tmp/libreport-attest.omg", NULL, 0);
|
|
|
2c83a8 |
+ printf("dd_create_archive() == %d\n", r);
|
|
|
2c83a8 |
+ assert(r == -ENOSYS || !"Not supported");
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ /* File already exists. */
|
|
|
2c83a8 |
+ dd_close(dd);
|
|
|
2c83a8 |
+ dd = dd_opendir(template, DD_OPEN_READONLY);
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "TEST-CASE: File exists\n");
|
|
|
2c83a8 |
+ fprintf(stdout, "TEST-CASE: File exists\n");
|
|
|
2c83a8 |
+ char file_contents[] = "Non emtpy file";
|
|
|
2c83a8 |
+ const char *file_name = "/tmp/libreport-attest.tar.gz";
|
|
|
2c83a8 |
+ FILE *test_file = fopen(file_name, "w");
|
|
|
2c83a8 |
+ assert(test_file != NULL);
|
|
|
2c83a8 |
+ assert(fprintf(test_file, "%s", file_contents) == strlen(file_contents));
|
|
|
2c83a8 |
+ fclose(test_file);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ assert(dd_create_archive(dd, file_name, NULL, 0) == -EEXIST || !"Exists");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ char *canary = xmalloc_xopen_read_close(file_name, NULL);
|
|
|
2c83a8 |
+ assert(canary != NULL);
|
|
|
2c83a8 |
+ assert(strcmp(canary, file_contents) == 0);
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ dd_close(dd);
|
|
|
2c83a8 |
+ dd = dd_opendir(template, DD_OPEN_READONLY);
|
|
|
2c83a8 |
+ /* All elements */
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "TEST-CASE: Compress all elements\n");
|
|
|
2c83a8 |
+ fprintf(stdout, "TEST-CASE: Compress all elements\n");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ const gchar *included_files[] = {
|
|
|
2c83a8 |
+ COMMON_FILES,
|
|
|
2c83a8 |
+ SENSITIVE_FILES,
|
|
|
2c83a8 |
+ NULL,
|
|
|
2c83a8 |
+ };
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ const char *file_name = "/tmp/libreport-attest-all.tar.gz";
|
|
|
2c83a8 |
+ unlink(file_name);
|
|
|
2c83a8 |
+ assert(dd_create_archive(dd, file_name, NULL, 0) == 0 || !"All elements");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ verify_archive(dd, file_name, included_files, NULL);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ unlink(file_name);
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ dd_close(dd);
|
|
|
2c83a8 |
+ dd = dd_opendir(template, DD_OPEN_READONLY);
|
|
|
2c83a8 |
+ /* Excluded elements */
|
|
|
2c83a8 |
+ {
|
|
|
2c83a8 |
+ fprintf(stderr, "TEST-CASE: Exclude elements\n");
|
|
|
2c83a8 |
+ fprintf(stdout, "TEST-CASE: Exclude elements\n");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ const char *included_files[] = {
|
|
|
2c83a8 |
+ COMMON_FILES,
|
|
|
2c83a8 |
+ NULL,
|
|
|
2c83a8 |
+ };
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ const char *file_name = "/tmp/libreport-attest-excluded.tar.gz";
|
|
|
2c83a8 |
+ unlink(file_name);
|
|
|
2c83a8 |
+ assert(dd_create_archive(dd, file_name, excluded_files, 0) == 0 || !"Excluded elements");
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ verify_archive(dd, file_name, included_files, excluded_files);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ unlink(file_name);
|
|
|
2c83a8 |
+ }
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ dd_close(dd);
|
|
|
2c83a8 |
+ dd = dd_opendir(template, DD_OPEN_READONLY);
|
|
|
2c83a8 |
+ assert(dd_delete(dd) == 0);
|
|
|
2c83a8 |
+
|
|
|
2c83a8 |
+ return 0;
|
|
|
2c83a8 |
+}
|
|
|
2c83a8 |
+]])
|
|
|
2c83a8 |
--
|
|
|
2c83a8 |
1.8.3.1
|
|
|
2c83a8 |
|