From 2ec5dbb5a2cc7cfd27313d5cd22baefbce2c9612 Mon Sep 17 00:00:00 2001 From: cedric Date: Thu, 15 Sep 2011 12:39:40 +0000 Subject: [PATCH] eina: add XAttr support to eina. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eina@63408 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- configure.ac | 24 +++++++++ src/include/eina_file.h | 47 ++++++++++++++++++ src/lib/eina_file.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) diff --git a/configure.ac b/configure.ac index abc583a..7c2a2d5 100644 --- a/configure.ac +++ b/configure.ac @@ -621,6 +621,29 @@ fi AC_SUBST([rt_libs]) +### Check for extended attribute + +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +#include + ]], + [[ +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}" diff --git a/src/include/eina_file.h b/src/include/eina_file.h index ca97440..c9067c7 100644 --- a/src/include/eina_file.h +++ b/src/include/eina_file.h @@ -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 diff --git a/src/lib/eina_file.c b/src/lib/eina_file.c index 211912b..fd76dd1 100644 --- a/src/lib/eina_file.c +++ b/src/lib/eina_file.c @@ -47,6 +47,10 @@ void *alloca (size_t); #include #include +#ifdef HAVE_XATTR +# include +#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) { -- 2.7.4