+static bxattr_exit_code unserialize_xattr_stream(JCR *jcr, alist *xattr_value_list)
+{
+ unser_declare;
+ xattr_t *current_xattr;
+ bxattr_exit_code retval = bxattr_exit_ok;
+
+ /*
+ * Parse the stream and call restore_xattr_on_file for each extended attribute.
+ *
+ * Start unserializing the data. We keep on looping while we have not
+ * unserialized all bytes in the stream.
+ */
+ unser_begin(jcr->xattr_data->content, jcr->xattr_data->content_length);
+ while (unser_length(jcr->xattr_data->content) < jcr->xattr_data->content_length) {
+ /*
+ * First make sure the magic is present. This way we can easily catch corruption.
+ * Any missing MAGIC is fatal we do NOT try to continue.
+ */
+
+ current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
+ unser_uint32(current_xattr->magic);
+ if (current_xattr->magic != XATTR_MAGIC) {
+ Mmsg1(jcr->errmsg, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
+ jcr->last_fname);
+ Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n",
+ jcr->last_fname);
+ free(current_xattr);
+ return bxattr_exit_error;
+ }
+
+ /*
+ * Decode the valuepair. First decode the length of the name.
+ */
+ unser_uint32(current_xattr->name_length);
+
+ /*
+ * Allocate room for the name and decode its content.
+ */
+ current_xattr->name = (char *)malloc(current_xattr->name_length + 1);
+ unser_bytes(current_xattr->name, current_xattr->name_length);
+
+ /*
+ * The xattr_name needs to be null terminated for lsetxattr.
+ */
+ current_xattr->name[current_xattr->name_length] = '\0';
+
+ /*
+ * Decode the value length.
+ */
+ unser_uint32(current_xattr->value_length);
+
+ /*
+ * Allocate room for the value and decode its content.
+ */
+ current_xattr->value = (char *)malloc(current_xattr->value_length);
+ unser_bytes(current_xattr->value, current_xattr->value_length);
+
+ xattr_value_list->append(current_xattr);
+ }
+
+ unser_end(jcr->xattr_data->content, jcr->xattr_data->content_length);
+ return retval;
+}
+#endif
+
+/*
+ * This is a supported OS, See what kind of interface we should use.
+ */
+#if defined(HAVE_DARWIN_OS) || \
+ defined(HAVE_LINUX_OS)
+
+#if (!defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)) || \
+ (!defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)) || \
+ (!defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR))
+#error "Missing either full support for the LXATTR or XATTR functions."
+#endif
+
+#ifdef HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#else
+#error "Missing sys/xattr.h header file"
+#endif
+
+/*
+ * Define the supported XATTR streams for this OS
+ */
+#if defined(HAVE_DARWIN_OS)
+static int os_default_xattr_streams[1] = { STREAM_XATTR_DARWIN };
+static const char *xattr_acl_skiplist[2] = { "com.apple.system.Security", NULL };
+static const char *xattr_skiplist[3] = { "com.apple.system.extendedsecurity", "com.apple.ResourceFork", NULL };
+#elif defined(HAVE_LINUX_OS)
+static int os_default_xattr_streams[1] = { STREAM_XATTR_LINUX };
+static const char *xattr_acl_skiplist[2] = { "system.posix_acl_access", NULL };
+static const char *xattr_skiplist[1] = { NULL };
+#endif
+
+/*
+ * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
+ * listxattr, getxattr and setxattr with an extra options argument
+ * which mimics the l variants of the functions when we specify
+ * XATTR_NOFOLLOW as the options value.
+ */
+#if defined(HAVE_DARWIN_OS)
+ #define llistxattr(path, list, size) listxattr((path), (list), (size), XATTR_NOFOLLOW)
+ #define lgetxattr(path, name, value, size) getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
+ #define lsetxattr(path, name, value, size, flags) setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
+#else
+ /*
+ * Fallback to the non l-functions when those are not available.
+ */
+ #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
+ #define lgetxattr getxattr
+ #endif
+ #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
+ #define lsetxattr setxattr
+ #endif
+ #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
+ #define llistxattr listxattr
+ #endif
+#endif
+
+static bxattr_exit_code linux_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)