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
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}"
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 {
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
#include <sys/mman.h>
#include <fcntl.h>
+#ifdef HAVE_XATTR
+# include <sys/xattr.h>
+#endif
+
#define PATH_DELIM '/'
#ifdef __sun
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
{
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;
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)
{
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)
{