forked from enlightenment/efl
eina: detect fault during Eina_File mmap memory access and improve Xattr functions.
SVN revision: 66799
This commit is contained in:
parent
2d1166d846
commit
edbee63134
|
@ -181,3 +181,10 @@
|
||||||
2011-12-30 Cedric Bail
|
2011-12-30 Cedric Bail
|
||||||
|
|
||||||
* Let eina_hash_free behave like free.
|
* Let eina_hash_free behave like free.
|
||||||
|
|
||||||
|
2012-01-03 Cedric Bail
|
||||||
|
|
||||||
|
* Add eina_xattr_fd_ls, eina_xattr_value_fd_ls and eina_xattr_value_ls.
|
||||||
|
* Detect fault during access to Eina_File mmap memory, use eina_file_map_faulted
|
||||||
|
to learn if it happens.
|
||||||
|
* Add eina_file_xattr_get and eina_file_xattr_value_get.
|
||||||
|
|
|
@ -7,7 +7,10 @@ Additions:
|
||||||
|
|
||||||
* eina_mempool_calloc
|
* eina_mempool_calloc
|
||||||
* Eina_Semaphore abstraction API
|
* Eina_Semaphore abstraction API
|
||||||
|
* eina_xattr_fd_ls
|
||||||
|
* Eina_Xattr iterator : eina_xattr_value_fd_ls and eina_xattr_value_ls API
|
||||||
|
* eina_file_map_faulted API
|
||||||
|
* Xattr iterator for Eina_File : eina_file_xattr_get and eina_file_xattr_value_get API
|
||||||
|
|
||||||
Eina 1.1.0
|
Eina 1.1.0
|
||||||
|
|
||||||
|
|
|
@ -347,6 +347,33 @@ EAPI time_t eina_file_mtime_get(Eina_File *file);
|
||||||
*/
|
*/
|
||||||
EAPI const char *eina_file_filename_get(Eina_File *file);
|
EAPI const char *eina_file_filename_get(Eina_File *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the eXtended attribute of an open file.
|
||||||
|
*
|
||||||
|
* @param file The file handler to request the eXtended attribute from.
|
||||||
|
* @return an iterator.
|
||||||
|
*
|
||||||
|
* The iterator will list all eXtended attribute name without allocating
|
||||||
|
* them, so you need to copy them yourself if needed.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the eXtended attribute of an open file.
|
||||||
|
*
|
||||||
|
* @param file The file handler to request the eXtended attribute from.
|
||||||
|
* @return an iterator.
|
||||||
|
*
|
||||||
|
* The iterator will list all eXtended attribute without allocating
|
||||||
|
* them, so you need to copy them yourself if needed. It is returning
|
||||||
|
* Eina_Xattr structure.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
EAPI Eina_Iterator *eina_file_xattr_value_get(Eina_File *file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Map all the file to a buffer.
|
* @brief Map all the file to a buffer.
|
||||||
*
|
*
|
||||||
|
@ -384,6 +411,16 @@ EAPI void *eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
|
||||||
*/
|
*/
|
||||||
EAPI void eina_file_map_free(Eina_File *file, void *map);
|
EAPI void eina_file_map_free(Eina_File *file, void *map);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tell if their was an IO error during the life of a mmaped file
|
||||||
|
*
|
||||||
|
* @param file The file handler to the mmaped file.
|
||||||
|
* @param map Memory map to check if an error occured on it.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
EAPI Eina_Bool eina_file_map_faulted(Eina_File *file, void *map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -39,6 +39,14 @@ typedef enum {
|
||||||
EINA_XATTR_CREATED /**< This will only succeed if the extended attribute wasn't previously set */
|
EINA_XATTR_CREATED /**< This will only succeed if the extended attribute wasn't previously set */
|
||||||
} Eina_Xattr_Flags;
|
} Eina_Xattr_Flags;
|
||||||
|
|
||||||
|
typedef struct _Eina_Xattr Eina_Xattr;
|
||||||
|
struct _Eina_Xattr
|
||||||
|
{
|
||||||
|
const char *name; /**< The eXtended attribute name @since 1.2 */
|
||||||
|
const char *value; /**< The eXtended attribute value @since 1.2 */
|
||||||
|
|
||||||
|
size_t length; /**< The length of the eXtended attribute value @since 1.2 */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get an iterator that list all extended attribute of a file.
|
* @brief Get an iterator that list all extended attribute of a file.
|
||||||
|
@ -53,6 +61,45 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Iterator *eina_xattr_ls(const char *file);
|
EAPI Eina_Iterator *eina_xattr_ls(const char *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get an iterator that list all extended attribute value related to a fd.
|
||||||
|
*
|
||||||
|
* @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. The iterator will provide an Eina_Xattr structure.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
EAPI Eina_Iterator *eina_xattr_value_ls(const char *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get an iterator that list all extended attribute related to a fd.
|
||||||
|
*
|
||||||
|
* @param fd The file descriptor 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.2
|
||||||
|
*/
|
||||||
|
EAPI Eina_Iterator *eina_xattr_fd_ls(int fd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get an iterator that list all extended attribute value related to a fd.
|
||||||
|
*
|
||||||
|
* @param fd The file descriptor 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. The iterator will provide an Eina_Xattr structure.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
EAPI Eina_Iterator *eina_xattr_value_fd_ls(int fd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve an extended attribute from a file.
|
* @brief Retrieve an extended attribute from a file.
|
||||||
*
|
*
|
||||||
|
|
|
@ -138,6 +138,7 @@ struct _Eina_File
|
||||||
|
|
||||||
Eina_Bool shared : 1;
|
Eina_Bool shared : 1;
|
||||||
Eina_Bool delete_me : 1;
|
Eina_Bool delete_me : 1;
|
||||||
|
Eina_Bool global_faulty : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _Eina_File_Map Eina_File_Map;
|
typedef struct _Eina_File_Map Eina_File_Map;
|
||||||
|
@ -151,6 +152,7 @@ struct _Eina_File_Map
|
||||||
int refcount;
|
int refcount;
|
||||||
|
|
||||||
Eina_Bool hugetlb : 1;
|
Eina_Bool hugetlb : 1;
|
||||||
|
Eina_Bool faulty : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Eina_Hash *_eina_file_cache = NULL;
|
static Eina_Hash *_eina_file_cache = NULL;
|
||||||
|
@ -1210,4 +1212,91 @@ eina_file_map_free(Eina_File *file, void *map)
|
||||||
eina_lock_release(&file->lock);
|
eina_lock_release(&file->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
eina_file_map_faulted(Eina_File *file, void *map)
|
||||||
|
{
|
||||||
|
Eina_File_Map *em;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
|
||||||
|
|
||||||
|
eina_lock_take(&file->lock);
|
||||||
|
|
||||||
|
if (file->global_map == map) return file->global_faulty;
|
||||||
|
|
||||||
|
em = eina_hash_find(file->rmap, &map);
|
||||||
|
if (!em) return EINA_FALSE;
|
||||||
|
|
||||||
|
return em->faulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Iterator *
|
||||||
|
eina_file_xattr_get(Eina_File *file)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
||||||
|
|
||||||
|
return eina_xattr_fd_ls(file->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Iterator *
|
||||||
|
eina_file_xattr_value_get(Eina_File *file)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
|
||||||
|
|
||||||
|
return eina_xattr_value_fd_ls(file->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eina_file_mmap_faulty(void *addr, long page_size)
|
||||||
|
{
|
||||||
|
Eina_File_Map *m;
|
||||||
|
Eina_File *f;
|
||||||
|
Eina_Iterator *itf;
|
||||||
|
Eina_Iterator *itm;
|
||||||
|
|
||||||
|
/* NOTE: I actually don't know if other thread are running, I will try to take the lock.
|
||||||
|
It may be possible that if other thread are not running and they were in the middle of
|
||||||
|
accessing an Eina_File this lock are still taken and we will result as a deadlock. */
|
||||||
|
eina_lock_take(&_eina_file_lock_cache);
|
||||||
|
|
||||||
|
itf = eina_hash_iterator_data_new(_eina_file_cache);
|
||||||
|
EINA_ITERATOR_FOREACH(itf, f)
|
||||||
|
{
|
||||||
|
Eina_Bool faulty = EINA_FALSE;
|
||||||
|
|
||||||
|
eina_lock_take(&f->lock);
|
||||||
|
|
||||||
|
if (f->global_map)
|
||||||
|
{
|
||||||
|
if ((unsigned char *) addr < (((unsigned char *)f->global_map) + f->length) &&
|
||||||
|
(((unsigned char *) addr) + page_size) >= (unsigned char *) f->global_map)
|
||||||
|
{
|
||||||
|
f->global_faulty = EINA_TRUE;
|
||||||
|
faulty = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!faulty)
|
||||||
|
{
|
||||||
|
itm = eina_hash_iterator_data_new(f->map);
|
||||||
|
EINA_ITERATOR_FOREACH(itm, m)
|
||||||
|
{
|
||||||
|
if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) &&
|
||||||
|
(((unsigned char *) addr) + page_size) >= (unsigned char *) m->map)
|
||||||
|
{
|
||||||
|
m->faulty = EINA_TRUE;
|
||||||
|
faulty = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eina_iterator_free(itm);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_lock_release(&f->lock);
|
||||||
|
|
||||||
|
if (faulty) break;
|
||||||
|
}
|
||||||
|
eina_iterator_free(itf);
|
||||||
|
|
||||||
|
eina_lock_release(&_eina_file_lock_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,8 @@ _eina_mmap_safe_sigbus(int sig __UNUSED__,
|
||||||
errno = perrno;
|
errno = perrno;
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
/* Look into mmaped Eina_File if it was one of them, just to remember for later request */
|
||||||
|
eina_file_mmap_faulty(addr, _eina_mmap_pagesize);
|
||||||
/* restore previous errno */
|
/* restore previous errno */
|
||||||
errno = perrno;
|
errno = perrno;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,5 +136,7 @@ void eina_log_threads_init(void);
|
||||||
void eina_log_threads_shutdown(void);
|
void eina_log_threads_shutdown(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void eina_file_mmap_faulty(void *addr, long page_size);
|
||||||
|
|
||||||
#endif /* EINA_PRIVATE_H_ */
|
#endif /* EINA_PRIVATE_H_ */
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "eina_safety_checks.h"
|
#include "eina_safety_checks.h"
|
||||||
#include "eina_xattr.h"
|
#include "eina_xattr.h"
|
||||||
#include "eina_convert.h"
|
#include "eina_convert.h"
|
||||||
|
#include "eina_stringshare.h"
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* Local *
|
* Local *
|
||||||
|
@ -50,13 +51,82 @@ struct _Eina_Xattr_Iterator
|
||||||
{
|
{
|
||||||
Eina_Iterator iterator;
|
Eina_Iterator iterator;
|
||||||
|
|
||||||
|
const char *file;
|
||||||
|
Eina_Xattr *attr;
|
||||||
|
|
||||||
ssize_t length;
|
ssize_t length;
|
||||||
ssize_t offset;
|
ssize_t offset;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
|
||||||
char xattr[1];
|
char xattr[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_XATTR
|
#ifdef HAVE_XATTR
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_xattr_value_ls_fd_iterator_next(Eina_Xattr_Iterator *it, void **data)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
if (it->offset >= it->length)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
*data = it->attr;
|
||||||
|
it->attr->name = it->xattr + it->offset;
|
||||||
|
|
||||||
|
it->attr->length = fgetxattr(it->fd, it->attr->name, NULL, 0);
|
||||||
|
if (it->attr->length)
|
||||||
|
{
|
||||||
|
tmp = realloc((void*) it->attr->value, it->attr->length);
|
||||||
|
if (!tmp)
|
||||||
|
{
|
||||||
|
free((void*) it->attr->value);
|
||||||
|
it->attr->value = NULL;
|
||||||
|
it->attr->length = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
it->attr->length = fgetxattr(it->fd, it->attr->name,
|
||||||
|
(void *) it->attr->value,
|
||||||
|
it->attr->length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_xattr_value_ls_iterator_next(Eina_Xattr_Iterator *it, void **data)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
if (it->offset >= it->length)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
*data = it->attr;
|
||||||
|
it->attr->name = it->xattr + it->offset;
|
||||||
|
|
||||||
|
it->attr->length = getxattr(it->file, it->attr->name, NULL, 0);
|
||||||
|
if (it->attr->length)
|
||||||
|
{
|
||||||
|
tmp = realloc((void*) it->attr->value, it->attr->length);
|
||||||
|
if (!tmp)
|
||||||
|
{
|
||||||
|
free((void*) it->attr->value);
|
||||||
|
it->attr->value = NULL;
|
||||||
|
it->attr->length = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
it->attr->length = getxattr(it->file, it->attr->name,
|
||||||
|
(void*) it->attr->value,
|
||||||
|
it->attr->length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_eina_xattr_ls_iterator_next(Eina_Xattr_Iterator *it, void **data)
|
_eina_xattr_ls_iterator_next(Eina_Xattr_Iterator *it, void **data)
|
||||||
{
|
{
|
||||||
|
@ -79,6 +149,9 @@ static void
|
||||||
_eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it)
|
_eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it)
|
||||||
{
|
{
|
||||||
EINA_MAGIC_SET(&it->iterator, 0);
|
EINA_MAGIC_SET(&it->iterator, 0);
|
||||||
|
if (it->attr) free((void *) it->attr->value);
|
||||||
|
eina_stringshare_del(it->file);
|
||||||
|
free(it->attr);
|
||||||
free(it);
|
free(it);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -97,6 +170,85 @@ _eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it)
|
||||||
* API *
|
* API *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
|
|
||||||
|
EAPI Eina_Iterator *
|
||||||
|
eina_xattr_value_fd_ls(int fd)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_XATTR
|
||||||
|
Eina_Xattr_Iterator *it;
|
||||||
|
ssize_t length;
|
||||||
|
|
||||||
|
if (fd < 0) return NULL;
|
||||||
|
|
||||||
|
length = flistxattr(fd, NULL, 0);
|
||||||
|
if (length <= 0) return NULL;
|
||||||
|
|
||||||
|
it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1);
|
||||||
|
if (!it) return NULL;
|
||||||
|
|
||||||
|
it->attr = calloc(1, sizeof (Eina_Xattr));
|
||||||
|
if (!it->attr)
|
||||||
|
{
|
||||||
|
free(it);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
||||||
|
|
||||||
|
it->fd = fd;
|
||||||
|
it->length = flistxattr(fd, 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_value_ls_fd_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;
|
||||||
|
(void)file;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Iterator *
|
||||||
|
eina_xattr_fd_ls(int fd)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_XATTR
|
||||||
|
Eina_Xattr_Iterator *it;
|
||||||
|
ssize_t length;
|
||||||
|
|
||||||
|
if (fd < 0) return NULL;
|
||||||
|
|
||||||
|
length = flistxattr(fd, 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 = flistxattr(fd, 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;
|
||||||
|
(void)file;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
EAPI Eina_Iterator *
|
EAPI Eina_Iterator *
|
||||||
eina_xattr_ls(const char *file)
|
eina_xattr_ls(const char *file)
|
||||||
|
@ -134,6 +286,44 @@ eina_xattr_ls(const char *file)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Iterator *
|
||||||
|
eina_xattr_value_ls(const char *file)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_XATTR
|
||||||
|
Eina_Xattr_Iterator *it;
|
||||||
|
ssize_t length;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(file, 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->file = eina_stringshare_add(file);
|
||||||
|
|
||||||
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
||||||
|
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_value_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;
|
||||||
|
(void)file;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
EAPI void *
|
EAPI void *
|
||||||
eina_xattr_get(const char *file, const char *attribute, ssize_t *size)
|
eina_xattr_get(const char *file, const char *attribute, ssize_t *size)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue