eina: add XAttr support to eina.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 15 Sep 2011 12:39:40 +0000 (12:39 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 15 Sep 2011 12:39:40 +0000 (12:39 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@63408 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/include/eina_file.h
src/lib/eina_file.c

index abc583a..7c2a2d5 100644 (file)
@@ -621,6 +621,29 @@ fi
 
 AC_SUBST([rt_libs])
 
+### Check for extended attribute
+
+AC_COMPILE_IFELSE(
+   [AC_LANG_PROGRAM(
+       [[
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+       ]],
+       [[
+size_t tmp = listxattr("/", NULL, 0);
+tmp = getxattr("/", "user.ethumb.md5", NULL, 0);
+setxattr("/", "user.ethumb.md5", NULL, 0, 0);
+       ]])],
+    [
+      AC_DEFINE(HAVE_XATTR, 1, [Define to 1 if you have 'listxattr', 'setxattr' and 'getxattr'])
+      have_xattr="yes"
+    ],
+    [have_xattr="no"])
+
+AC_MSG_CHECKING([for Xattr])
+AC_MSG_RESULT([${have_xattr}])
+
 ### Modules
 
 if test "x${have_default_mempool}" = "xyes" ; then
@@ -736,6 +759,7 @@ fi
 echo "  Amalgamation.........: ${do_amalgamation}"
 echo "  Iconv support........: ${have_iconv}"
 echo "  File dirfd...........: ${have_dirfd}"
+echo "  File xattr...........: ${have_xattr}"
 echo
 echo "  Documentation........: ${build_doc}"
 echo "  Tests................: ${enable_tests}"
index ca97440..c9067c7 100644 (file)
@@ -112,6 +112,12 @@ typedef enum {
   EINA_FILE_WHT      /**< Whiteout file type (unused on Windows). */
 } Eina_File_Type;
 
+typedef enum {
+  EINA_XATTR_INSERT, /**< This is the default behaviour, it will either create or replace the extended attribute */
+  EINA_XATTR_REPLACE, /**< This will only succeed if the extended attribute previously existed */
+  EINA_XATTR_CREATED /**< This will only succeed if the extended attribute wasn't previously set */
+} Eina_Xattr_Flags;
+
 typedef struct _Eina_File Eina_File;
 
 typedef enum {
@@ -274,6 +280,47 @@ EAPI Eina_Iterator *eina_file_stat_ls(const char *dir) EINA_WARN_UNUSED_RESULT E
 EAPI Eina_Iterator *eina_file_direct_ls(const char *dir) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
 
 /**
+ * @brief Get an iterator that list all extended attribute of a file.
+ *
+ * @param file The filename to retrieve the extended attribute list from.
+ * @return an iterator.
+ *
+ * The iterator will not allocate any data during the iteration step, so you need to copy them yourself
+ * if you need.
+ *
+ * @since 1.1
+ */
+EAPI Eina_Iterator *eina_xattr_ls(const char *file);
+
+/**
+ * @brief Retrieve an extended attribute from a file.
+ *
+ * @param file The file to retrieve the extended attribute from.
+ * @param atttribute The extended attribute name to retrieve.
+ * @param size The size of the retrieved extended attribute.
+ * @return the allocated data that hold the extended attribute value.
+ *
+ * It will return NULL and *size will be @c 0 if it fails.
+ *
+ * @since 1.1
+ */
+EAPI void *eina_xattr_get(const char *file, const char *attribute, ssize_t *size);
+
+/**
+ * @brief Set an extended attribute on a file.
+ *
+ * @param file The file to set the extended attribute to.
+ * @param attribute The attribute to set.
+ * @param data The data to set.
+ * @param length The length of the data to set.
+ * @param flags Define the set policy
+ * @return EINA_TRUE on success, EINA_FALSE otherwise.
+ *
+ * @since 1.1
+ */
+EAPI Eina_Bool eina_xattr_set(const char *file, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags);
+
+/**
  * @brief Get a read-only handler to a file.
  *
  * @param name Filename to open
index 211912b..fd76dd1 100644 (file)
@@ -47,6 +47,10 @@ void *alloca (size_t);
 #include <sys/mman.h>
 #include <fcntl.h>
 
+#ifdef HAVE_XATTR
+# include <sys/xattr.h>
+#endif
+
 #define PATH_DELIM '/'
 
 #ifdef __sun
@@ -99,6 +103,7 @@ void *alloca (size_t);
 
 typedef struct _Eina_File_Iterator Eina_File_Iterator;
 typedef struct _Eina_File_Map Eina_File_Map;
+typedef struct _Eina_Xattr_Iterator Eina_Xattr_Iterator;
 
 struct _Eina_File_Iterator
 {
@@ -110,6 +115,16 @@ struct _Eina_File_Iterator
    char dir[1];
 };
 
+struct _Eina_Xattr_Iterator
+{
+   Eina_Iterator iterator;
+
+   ssize_t length;
+   ssize_t offset;
+
+   char xattr[1];
+};
+
 struct _Eina_File
 {
    const char *filename;
@@ -379,6 +394,33 @@ _eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
    return EINA_TRUE;
 }
 
+#ifdef HAVE_XATTR
+static Eina_Bool
+_eina_xattr_ls_iterator_next(Eina_Xattr_Iterator *it, void **data)
+{
+   if (it->offset >= it->length)
+     return EINA_FALSE;
+
+   *data = it->xattr + it->offset;
+   it->offset += strlen(it->xattr + it->offset) + 1;
+
+   return EINA_TRUE;
+}
+
+static void *
+_eina_xattr_ls_iterator_container(Eina_Xattr_Iterator *it __UNUSED__)
+{
+   return NULL;
+}
+
+static void
+_eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it)
+{
+   EINA_MAGIC_SET(&it->iterator, 0);
+   free(it);
+}
+#endif
+
 static void
 _eina_file_real_close(Eina_File *file)
 {
@@ -736,6 +778,91 @@ eina_file_stat_ls(const char *dir)
    return &it->iterator;
 }
 
+EAPI Eina_Iterator *
+eina_xattr_ls(const char *file)
+{
+   Eina_Xattr_Iterator *it;
+   ssize_t length;
+
+#ifdef HAVE_XATTR
+   if (!file)
+     return NULL;
+
+   length = listxattr(file, NULL, 0);
+   if (length <= 0) return NULL;
+
+   it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1);
+   if (!it) return NULL;
+
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);       
+
+   it->length = listxattr(file, it->xattr, length);
+   if (it->length != length)
+     {
+        free(it);
+       return NULL;
+     }
+
+   it->iterator.version = EINA_ITERATOR_VERSION;
+   it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_ls_iterator_next);
+   it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container);
+   it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free);
+
+   return &it->iterator;
+#else
+   return NULL;
+#endif
+}
+
+EAPI void *
+eina_xattr_get(const char *file, const char *attribute, ssize_t *size)
+{
+   void *ret = NULL;
+   ssize_t tmp;
+
+   if (!size || !file || !attribute) return NULL;
+   *size = getxattr(file, attribute, NULL, 0);
+   /* Size should be less than 2MB (already huge in my opinion) */
+   if (!(*size > 0 && *size < 2 * 1024 * 1024))
+     goto on_error;
+
+   ret = malloc(*size);
+   if (!ret) return NULL;
+
+   tmp = getxattr(file, attribute, ret, *size);
+   if (tmp != *size)
+     goto on_error;
+
+   return ret;
+
+ on_error:
+   free(ret);
+   *size = 0;
+   return NULL;
+}
+
+EAPI Eina_Bool
+eina_xattr_set(const char *file, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags)
+{
+   int iflags;
+
+   if (!file || !attribute || !data || length <= 0 || length > 2 * 1024 * 1024)
+     return EINA_FALSE;
+
+   switch (flags)
+     {
+     case EINA_XATTR_INSERT: iflags = 0; break;
+     case EINA_XATTR_REPLACE: iflags = XATTR_REPLACE; break;
+     case EINA_XATTR_CREATED: iflags = XATTR_CREATE; break;
+     default:
+       return EINA_FALSE;
+     }
+
+   if (setxattr(file, attribute, data, length, iflags))
+     return EINA_FALSE;
+   return EINA_TRUE;
+}
+
 EAPI Eina_File *
 eina_file_open(const char *filename, Eina_Bool shared)
 {