forked from enlightenment/efl
parent
8e9fbe5662
commit
680170b3f9
|
@ -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}"
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue