diff --git a/legacy/eio/src/lib/Eio.h b/legacy/eio/src/lib/Eio.h index 28cf38f1ef..fae939b020 100644 --- a/legacy/eio/src/lib/Eio.h +++ b/legacy/eio/src/lib/Eio.h @@ -90,6 +90,17 @@ enum _Eio_File_Op EIO_FILE_GETGRNAM /**< IO operation is trying to get gid from user name */ }; +/** + * @enum Eio_Xattr_Flags + * Xattr creation flags + */ +typedef enum +{ + EIO_XATTR_INSERT = 0, /**< Xattr will always be set */ + EIO_XATTR_CREATED, /**< Xattr will be created, but will fail if already exists */ + EIO_XATTR_REPLACE /**< Xattr will replace the existing value or fail if no value exist before */ +} Eio_Xattr_Flags; + /** * @typedef Eio_File_Op * Input/Output operations on files. @@ -117,6 +128,8 @@ typedef void (*Eio_Main_Direct_Cb)(void *data, Eio_File *handler, const Eina_Fil typedef void (*Eio_Stat_Cb)(void *data, Eio_File *handler, const struct stat *stat); typedef void (*Eio_Progress_Cb)(void *data, Eio_File *handler, const Eio_Progress *info); +typedef void (*Eio_Done_Length_Cb)(void *data, Eio_File *handler, const char *xattr_data, unsigned int xattr_size); + typedef void (*Eio_Done_Cb)(void *data, Eio_File *handler); typedef void (*Eio_Error_Cb)(void *data, Eio_File *handler, int error); @@ -236,6 +249,21 @@ EAPI Eio_File *eio_file_xattr(const char *path, Eio_Error_Cb error_cb, const void *data); +EAPI Eio_File *eio_file_xattr_set(const char *path, + const char *attribute, + const char *xattr_data, + unsigned int xattr_size, + Eio_Xattr_Flags flags, + Eio_Done_Cb done_cb, + Eio_Error_Cb error_cb, + const void *data); + +EAPI Eio_File *eio_file_xattr_get(const char *path, + const char *attribute, + Eio_Done_Length_Cb done_cb, + Eio_Error_Cb error_cb, + const void *data); + EAPI void *eio_file_container_get(Eio_File *ls); EAPI Eina_Bool eio_file_cancel(Eio_File *ls); diff --git a/legacy/eio/src/lib/eio_private.h b/legacy/eio/src/lib/eio_private.h index 9ec212660d..fa88a9b001 100644 --- a/legacy/eio/src/lib/eio_private.h +++ b/legacy/eio/src/lib/eio_private.h @@ -61,6 +61,8 @@ typedef struct _Eio_File_Move Eio_File_Move; typedef struct _Eio_File_Chown Eio_File_Chown; typedef struct _Eio_Monitor_Backend Eio_Monitor_Backend; +typedef struct _Eio_File_Xattr Eio_File_Xattr; + typedef struct _Eio_Dir_Copy Eio_Dir_Copy; typedef struct _Eio_File_Direct_Info Eio_File_Direct_Info; @@ -152,6 +154,20 @@ struct _Eio_File_Stat const char *path; }; +struct _Eio_File_Xattr +{ + Eio_File common; + + Eio_Done_Length_Cb done_cb; + + const char *path; + const char *attribute; + int flags; + + char *xattr_data; + unsigned int xattr_size; +}; + struct _Eio_File_Progress { Eio_File common; diff --git a/legacy/eio/src/lib/eio_xattr.c b/legacy/eio/src/lib/eio_xattr.c index 3ac18212a5..fba24ecbf0 100644 --- a/legacy/eio/src/lib/eio_xattr.c +++ b/legacy/eio/src/lib/eio_xattr.c @@ -78,6 +78,95 @@ _eio_ls_xattr_notify(void *data, Ecore_Thread *thread __UNUSED__, void *msg_data async->main_cb((void*) async->ls.common.data, &async->ls.common, xattr); } + +static void +_eio_file_xattr_get(void *data, Ecore_Thread *thread) +{ + Eio_File_Xattr *async = data; + ssize_t sz; + + async->xattr_size = 0; + async->xattr_data = NULL; + + sz = getxattr(async->path, async->attribute, NULL, 0); + if (sz > 0 && sz < 2 * 1024 * 1024) /* sz should be smaller than 2MB (already huge in my opinion) */ + { + async->xattr_data = malloc(sz); + async->xattr_size = (unsigned int) sz; + + sz = getxattr(async->path, async->attribute, async->xattr_data, async->xattr_size); + if (sz != async->xattr_size) + { + free(async->xattr_data); + async->xattr_data = NULL; + async->xattr_size = 0; + + ecore_thread_cancel(thread); + } + } + else + ecore_thread_cancel(thread); +} + +static void +_eio_file_xattr_free(Eio_File_Xattr *async) +{ + eina_stringshare_del(async->path); + eina_stringshare_del(async->attribute); + free(async->xattr_data); + free(async); +} + +static void +_eio_file_xattr_get_done(void *data, Ecore_Thread *thread __UNUSED__) +{ + Eio_File_Xattr *async = data; + + if (async->done_cb) + async->done_cb((void *) async->common.data, &async->common, async->xattr_data, async->xattr_size); + + _eio_file_xattr_free(async); +} + +static void +_eio_file_xattr_get_error(void *data, Ecore_Thread *thread __UNUSED__) +{ + Eio_File_Xattr *async = data; + + eio_file_error(&async->common); + _eio_file_xattr_free(async); +} + +static void +_eio_file_xattr_set(void *data, Ecore_Thread *thread) +{ + Eio_File_Xattr *async = data; + + if (setxattr(async->path, async->attribute, async->xattr_data, async->xattr_size, async->flags)) + eio_file_thread_error(&async->common, thread); + async->xattr_data = NULL; +} + +static void +_eio_file_xattr_set_done(void *data, Ecore_Thread *thread __UNUSED__) +{ + Eio_File_Xattr *async = data; + + if (async->common.done_cb) + async->common.done_cb((void*) async->common.data, &async->common); + + _eio_file_xattr_free(async); +} + +static void +_eio_file_xattr_set_error(void *data, Ecore_Thread *thread __UNUSED__) +{ + Eio_File_Xattr *async = data; + + eio_file_error(&async->common); + _eio_file_xattr_free(async); +} + #endif /** @@ -147,6 +236,114 @@ eio_file_xattr(const char *path, #endif } +/** + * @brief Retrieve the extended attribute of a file/directory. + * @param path The path to retrieve the extended attribute from. + * @param attribute The name of the attribute to retrieve. + * @param done_cb Callback called from the main loop when getxattr succeeded. + * @param error_cb Callback called from the main loop when getxattr failed or has been canceled. + * @param data Private data given to callback. + * @return A reference to the IO operation. + * + * eio_file_xattr_get call getxattr from another thread. This prevent lock in your apps. + */ + +EAPI Eio_File * +eio_file_xattr_get(const char *path, + const char *attribute, + Eio_Done_Length_Cb done_cb, + Eio_Error_Cb error_cb, + const void *data) +{ +#ifdef HAVE_XATTR + Eio_File_Xattr *async; + + if (!path || !attribute || !done_cb || !error_cb) + return NULL; + + async = malloc(sizeof (Eio_File_Xattr)); + if (!async) return NULL; + + async->path = eina_stringshare_add(path); + async->attribute = eina_stringshare_add(attribute); + async->done_cb = done_cb; + + if (!eio_file_set(&async->common, + NULL, + error_cb, + data, + _eio_file_xattr_get, + _eio_file_xattr_get_done, + _eio_file_xattr_get_error)) + return NULL; + + return &async->common; +#else + return NULL; +#endif +} + +/** + * @brief Define the extented attribute on a file/directory. + * @param path The path to set the attribute on. + * @param attribute The name of the attribute to define. + * @param xattr_data The data to link the attribute with. + * @param xattr_size The size of the data to set. + * @param done_cb The callback called from the main loop when setxattr succeeded. + * @param error_cb The callback called from the main loop when setxattr failed. + * @param data Private data given to callback. + * @return A reference to the IO operation. + * + * eio_file_xattr_set call setxattr from another thread. This prevent lock in your apps. If + * the writing succeeded, the done_cb will be called even if a cancel was requested, but came to late. + */ +EAPI Eio_File * +eio_file_xattr_set(const char *path, + const char *attribute, + const char *xattr_data, + unsigned int xattr_size, + Eio_Xattr_Flags flags, + Eio_Done_Cb done_cb, + Eio_Error_Cb error_cb, + const void *data) +{ + Eio_File_Xattr *async; + int iflags; + + if (!path || !attribute || !done_cb || !xattr_data || !xattr_size || !error_cb) + return NULL; + + switch (flags) + { + case EIO_XATTR_INSERT: iflags = 0; break; + case EIO_XATTR_REPLACE: iflags = XATTR_REPLACE; break; + case EIO_XATTR_CREATED: iflags = XATTR_CREATE; break; + default: + return NULL; + } + + async = malloc(sizeof (Eio_File_Xattr) + xattr_size); + if (!async) return NULL; + + async->path = eina_stringshare_add(path); + async->attribute = eina_stringshare_add(attribute); + async->xattr_size = xattr_size; + async->xattr_data = (char*) (async + 1); + memcpy(async->xattr_data, xattr_data, xattr_size); + async->flags = iflags; + + if (!eio_file_set(&async->common, + done_cb, + error_cb, + data, + _eio_file_xattr_set, + _eio_file_xattr_set_done, + _eio_file_xattr_set_error)) + return NULL; + + return &async->common; +} + /** * @} */