Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/libvirt_private.syms | 3 +
src/util/virfile.c | 121 +++++++++++++++++++++++++++++++++++++++
src/util/virfile.h | 11 ++++
3 files changed, 135 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fd63c9ca61..9835e9a56c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1830,6 +1830,7 @@ virFileGetACLs;
virFileGetHugepageSize;
virFileGetMountReverseSubtree;
virFileGetMountSubtree;
+virFileGetXAttr;
virFileHasSuffix;
virFileInData;
virFileIsAbsPath;
@@ -1869,6 +1870,7 @@ virFileReadValueUint;
virFileRelLinkPointsTo;
virFileRemove;
virFileRemoveLastComponent;
+virFileRemoveXAttr;
virFileResolveAllLinks;
virFileResolveLink;
virFileRewrite;
@@ -1876,6 +1878,7 @@ virFileRewriteStr;
virFileSanitizePath;
virFileSetACLs;
virFileSetupDev;
+virFileSetXAttr;
virFileSkipRoot;
virFileStripSuffix;
virFileTouch;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index f6f9e4ceda..263c92667c 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -64,6 +64,10 @@
# include <linux/cdrom.h>
#endif
+#if HAVE_LIBATTR
+# include <sys/xattr.h>
+#endif
+
#include "configmake.h"
#include "intprops.h"
#include "vircommand.h"
@@ -4354,3 +4358,120 @@ virFileWaitForExists(const char *path,
return 0;
}
+
+
+#if HAVE_LIBATTR
+/**
+ * virFileGetXAttr;
+ * @path: a filename
+ * @name: name of xattr
+ * @value: read value
+ *
+ * Reads xattr with @name for given @path and stores it into
+ * @value. Caller is responsible for freeing @value.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise (with errno set).
+ */
+int
+virFileGetXAttr(const char *path,
+ const char *name,
+ char **value)
+{
+ char *buf = NULL;
+ int ret = -1;
+
+ /* We might be racing with somebody who sets the same attribute. */
+ while (1) {
+ ssize_t need;
+ ssize_t got;
+
+ /* The first call determines how many bytes we need to allocate. */
+ if ((need = getxattr(path, name, NULL, 0)) < 0)
+ goto cleanup;
+
+ if (VIR_REALLOC_N_QUIET(buf, need + 1) < 0)
+ goto cleanup;
+
+ if ((got = getxattr(path, name, buf, need)) < 0) {
+ if (errno == ERANGE)
+ continue;
+ goto cleanup;
+ }
+
+ buf[got] = '\0';
+ break;
+ }
+
+ VIR_STEAL_PTR(*value, buf);
+ ret = 0;
+ cleanup:
+ VIR_FREE(buf);
+ return ret;
+}
+
+/**
+ * virFileSetXAttr:
+ * @path: a filename
+ * @name: name of xattr
+ * @value: value to set
+ *
+ * Sets xattr of @name and @value on @path.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise (with errno set).
+ */
+int
+virFileSetXAttr(const char *path,
+ const char *name,
+ const char *value)
+{
+ return setxattr(path, name, value, strlen(value), 0);
+}
+
+/**
+ * virFileRemoveXAttr:
+ * @path: a filename
+ * @name: name of xattr
+ *
+ * Remove xattr of @name on @path.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise (with errno set).
+ */
+int
+virFileRemoveXAttr(const char *path,
+ const char *name)
+{
+ return removexattr(path, name);
+}
+
+#else /* !HAVE_LIBATTR */
+
+int
+virFileGetXAttr(const char *path ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED,
+ char **value ATTRIBUTE_UNUSED)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+virFileSetXAttr(const char *path ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED,
+ const char *value ATTRIBUTE_UNUSED)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+virFileRemoveXAttr(const char *path ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif /* HAVE_LIBATTR */
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 0f7dece958..aa4c29dc40 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -383,4 +383,15 @@ int virFileInData(int fd,
VIR_DEFINE_AUTOPTR_FUNC(virFileWrapperFd, virFileWrapperFdFree)
+int virFileGetXAttr(const char *path,
+ const char *name,
+ char **value);
+
+int virFileSetXAttr(const char *path,
+ const char *name,
+ const char *value);
+
+int virFileRemoveXAttr(const char *path,
+ const char *name);
+
#endif /* __VIR_FILE_H */
--
2.19.2