+#ifndef _WIMLIB_XATTR_H
+#define _WIMLIB_XATTR_H
+
+#include "wimlib/endianness.h"
+#include "wimlib/sha1.h"
+#include "wimlib/tagged_items.h"
+#include "wimlib/util.h"
+
+#undef HAVE_XATTR_SUPPORT
+#if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LLISTXATTR) && \
+ defined(HAVE_LGETXATTR) && defined(HAVE_FSETXATTR)
+# define HAVE_XATTR_SUPPORT 1
+#endif
+
+/*
+ * On-disk format of an entry in an extended attribute stream (wimlib
+ * extension). An xattr stream consists of a series of variable-length xattr
+ * entries, each of which begins with this entry header.
+ *
+ * Currently this is only used for Linux-style xattrs, but in the future we may
+ * use this for Windows-style xattrs too.
+ */
+struct wimlib_xattr_entry {
+
+ /* length of xattr name in bytes */
+ le16 name_len;
+
+ /* reserved, must be 0 */
+ le16 reserved;
+
+ /* length of xattr value in bytes, not counting padding */
+ le32 value_len;
+
+ /* followed by the name with no terminating null */
+ char name[0];
+
+ /*
+ * directly followed by the value, zero-padded to the next 4-byte
+ * boundary if not already aligned
+ */
+ /* u8 value[0]; */
+};
+
+static inline size_t
+xattr_entry_size(const struct wimlib_xattr_entry *entry)
+{
+ return ALIGN(sizeof(*entry) + le16_to_cpu(entry->name_len) +
+ le32_to_cpu(entry->value_len), 4);
+}
+
+static inline struct wimlib_xattr_entry *
+xattr_entry_next(const struct wimlib_xattr_entry *entry)
+{
+ return (void *)entry + xattr_entry_size(entry);
+}
+
+/* Currently we use the Linux limits when validating xattr names and values */
+#define XATTR_NAME_MAX 255
+#define XATTR_SIZE_MAX 65536
+
+static inline bool
+valid_xattr_entry(const struct wimlib_xattr_entry *entry, size_t avail)
+{
+ if (avail < sizeof(*entry))
+ return false;
+
+ if (entry->name_len == 0 ||
+ le16_to_cpu(entry->name_len) > XATTR_NAME_MAX)
+ return false;
+
+ if (entry->reserved != 0)
+ return false;
+
+ if (le32_to_cpu(entry->value_len) > XATTR_SIZE_MAX)
+ return false;
+
+ return avail >= xattr_entry_size(entry);
+}
+
+static inline const u8 *
+inode_get_linux_xattr_hash(const struct wim_inode *inode)
+{
+ return inode_get_tagged_item(inode, TAG_WIMLIB_LINUX_XATTR_HASH,
+ SHA1_HASH_SIZE, NULL);
+}
+
+static inline bool
+inode_has_linux_xattr_hash(const struct wim_inode *inode)
+{
+ return inode_get_linux_xattr_hash(inode) != NULL;
+}
+
+static inline bool
+inode_set_linux_xattr_hash(struct wim_inode *inode, const u8 *hash)
+{
+ return inode_set_tagged_data(inode, TAG_WIMLIB_LINUX_XATTR_HASH,
+ hash, SHA1_HASH_SIZE);
+}
+
+#endif /* _WIMLIB_XATTR_H */