diff --git a/legacy/eina/ChangeLog b/legacy/eina/ChangeLog index 8f0b210b09..6a1846bdb9 100644 --- a/legacy/eina/ChangeLog +++ b/legacy/eina/ChangeLog @@ -151,7 +151,7 @@ 2011-12-02 Carsten Haitzler (The Rasterman) 1.1.0 release - + 2011-12-02 Mike Blumenkrantz (discomfitor/zmike) * Add eina_mempool_calloc for returning zeroed memory @@ -181,3 +181,10 @@ 2011-12-30 Cedric Bail * 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. diff --git a/legacy/eina/NEWS b/legacy/eina/NEWS index 5e042e9ddb..6123cdd914 100644 --- a/legacy/eina/NEWS +++ b/legacy/eina/NEWS @@ -7,7 +7,10 @@ Additions: * eina_mempool_calloc * 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 diff --git a/legacy/eina/src/include/eina_file.h b/legacy/eina/src/include/eina_file.h index 295da0922f..422fb65b57 100644 --- a/legacy/eina/src/include/eina_file.h +++ b/legacy/eina/src/include/eina_file.h @@ -347,6 +347,33 @@ EAPI time_t eina_file_mtime_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. * @@ -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); +/** + * @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); + /** * @} */ diff --git a/legacy/eina/src/include/eina_xattr.h b/legacy/eina/src/include/eina_xattr.h index 5ab294d04d..0f89cc3cdb 100644 --- a/legacy/eina/src/include/eina_xattr.h +++ b/legacy/eina/src/include/eina_xattr.h @@ -39,6 +39,14 @@ typedef enum { EINA_XATTR_CREATED /**< This will only succeed if the extended attribute wasn't previously set */ } 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. @@ -53,6 +61,45 @@ typedef enum { */ 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. * diff --git a/legacy/eina/src/lib/eina_file.c b/legacy/eina/src/lib/eina_file.c index c53f674a08..6f1b0f1d4c 100644 --- a/legacy/eina/src/lib/eina_file.c +++ b/legacy/eina/src/lib/eina_file.c @@ -138,6 +138,7 @@ struct _Eina_File Eina_Bool shared : 1; Eina_Bool delete_me : 1; + Eina_Bool global_faulty : 1; }; typedef struct _Eina_File_Map Eina_File_Map; @@ -151,6 +152,7 @@ struct _Eina_File_Map int refcount; Eina_Bool hugetlb : 1; + Eina_Bool faulty : 1; }; 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); } +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); +} diff --git a/legacy/eina/src/lib/eina_mmap.c b/legacy/eina/src/lib/eina_mmap.c index fb27bd79ca..45898187e2 100644 --- a/legacy/eina/src/lib/eina_mmap.c +++ b/legacy/eina/src/lib/eina_mmap.c @@ -110,6 +110,8 @@ _eina_mmap_safe_sigbus(int sig __UNUSED__, errno = perrno; 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 */ errno = perrno; } diff --git a/legacy/eina/src/lib/eina_private.h b/legacy/eina/src/lib/eina_private.h index d3903972a2..6db120c77a 100644 --- a/legacy/eina/src/lib/eina_private.h +++ b/legacy/eina/src/lib/eina_private.h @@ -136,5 +136,7 @@ void eina_log_threads_init(void); void eina_log_threads_shutdown(void); #endif +void eina_file_mmap_faulty(void *addr, long page_size); + #endif /* EINA_PRIVATE_H_ */ diff --git a/legacy/eina/src/lib/eina_xattr.c b/legacy/eina/src/lib/eina_xattr.c index 893456b454..7f86f2fdc3 100644 --- a/legacy/eina/src/lib/eina_xattr.c +++ b/legacy/eina/src/lib/eina_xattr.c @@ -35,6 +35,7 @@ #include "eina_safety_checks.h" #include "eina_xattr.h" #include "eina_convert.h" +#include "eina_stringshare.h" /*============================================================================* * Local * @@ -50,13 +51,82 @@ struct _Eina_Xattr_Iterator { Eina_Iterator iterator; + const char *file; + Eina_Xattr *attr; + ssize_t length; ssize_t offset; + int fd; + char xattr[1]; }; #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 _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_MAGIC_SET(&it->iterator, 0); + if (it->attr) free((void *) it->attr->value); + eina_stringshare_del(it->file); + free(it->attr); free(it); } #endif @@ -97,6 +170,85 @@ _eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it) * 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 * eina_xattr_ls(const char *file) @@ -134,6 +286,44 @@ eina_xattr_ls(const char *file) #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 * eina_xattr_get(const char *file, const char *attribute, ssize_t *size) {