eina: add XAttr support to eina.

SVN revision: 63408
This commit is contained in:
Cedric BAIL 2011-09-15 12:39:40 +00:00
parent 8e9fbe5662
commit 680170b3f9
3 changed files with 198 additions and 0 deletions

View 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}"

View 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 {
@ -273,6 +279,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.
*

View 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)
{