diff --git a/ChangeLog b/ChangeLog index 2ba08fa297..fc12aad747 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-12-31 Gustavo Sverzut Barbieri (k-s) + + * Fixed eina_xattr_value_ls() an eina_xattr_value_fd_ls() + * Added eina_xattr_fd_get(), eina_xattr_fd_set(), + eina_xattr_del(), eina_xattr_fd_del(), eina_xattr_copy() and + eina_xattr_fd_copy() + 2012-12-24 Mike Blumenkrantz * eina_magic_fail() now throws error messages on NULL pointers instead of critical diff --git a/NEWS b/NEWS index 8aa4acfd7a..e058062758 100644 --- a/NEWS +++ b/NEWS @@ -43,6 +43,9 @@ Additions: - Add ellipsis support in Evas_Object_Text. - Add EVAS_GL_LINE_OFFSET_HACK_DISABLE to turn off line shift correction by evas. * Add ecore_audio API + * Added eina_xattr_fd_get(), eina_xattr_fd_set(), + eina_xattr_del(), eina_xattr_fd_del(), eina_xattr_copy() and + eina_xattr_fd_copy() Deprecations: * ecore_x: @@ -89,3 +92,4 @@ Fixes: * Fix Evas RGBA_Image->flags.loaded for copied images. * Fix evas_object_image_is_inside() * eio functions no longer crash when passed NULL and throw errors accordingly + * Fix eina_xattr_value_ls() and eina_xattr_value_fd_ls() diff --git a/src/examples/eina/Makefile.am b/src/examples/eina/Makefile.am index fe57e5ec57..f35db42840 100644 --- a/src/examples/eina/Makefile.am +++ b/src/examples/eina/Makefile.am @@ -42,7 +42,10 @@ eina_value_02.c \ eina_value_03.c \ eina_inarray_01.c \ eina_inarray_02.c \ -eina_magic_01.c +eina_magic_01.c \ +eina_xattr_01.c \ +eina_xattr_02.c + #eina_model_01.c \ #eina_model_02.c \ #eina_model_03.c @@ -81,7 +84,10 @@ eina_value_01 \ eina_value_02 \ eina_value_03 \ eina_inarray_01 \ -eina_inarray_02 +eina_inarray_02 \ +eina_xattr_01 \ +eina_xattr_02 + #eina_model_01 \ #eina_model_02 \ #eina_model_03 \ diff --git a/src/examples/eina/eina_xattr_01.c b/src/examples/eina/eina_xattr_01.c new file mode 100644 index 0000000000..c26c441941 --- /dev/null +++ b/src/examples/eina/eina_xattr_01.c @@ -0,0 +1,93 @@ +//Compile with: +//gcc -g eina_xattr_02.c -o eina_xattr_02 `pkg-config --cflags --libs eina` + +#include + +int +main(int argc, char **argv) +{ + if (argc < 3) + { + fprintf(stderr, "ERROR: incorrect usage.\n" + "Usage:\n" + "\t%s list \n" + "\t%s get \n" + "\t%s del \n" + "\t%s set \n", + argv[0], argv[0], argv[0]); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "list") == 0) + { + Eina_Iterator *itr; + Eina_Xattr *xattr; + + printf("xattrs of %s:\n", argv[2]); + + eina_init(); + + itr = eina_xattr_value_ls(argv[2]); + EINA_ITERATOR_FOREACH(itr, xattr) + printf("\t%s: %.*s\n", xattr->name, xattr->length, xattr->value); + eina_iterator_free(itr); + + eina_shutdown(); + + } + else if (strcmp(argv[1], "get") == 0) + { + size_t size = 0; + const char *value; + + if (argc < 4) + { + fputs("ERROR: missing key\n", stderr); + return EXIT_FAILURE; + } + + eina_init(); + value = eina_xattr_get(argv[2], argv[3], &size); + printf("%s: %.*s\n", argv[3], (int)size, value); + eina_shutdown(); + } + else if (strcmp(argv[1], "del") == 0) + { + Eina_Bool ret; + + if (argc < 4) + { + fputs("ERROR: missing key\n", stderr); + return EXIT_FAILURE; + } + + eina_init(); + ret = eina_xattr_del(argv[2], argv[3]); + printf("del xattr '%s': %s\n", argv[3], ret ? "success" : "failure"); + eina_shutdown(); + } + else if (strcmp(argv[1], "set") == 0) + { + size_t size = 0; + const char *value; + Eina_Bool ret; + + if (argc < 5) + { + fputs("ERROR: missing key or value\n", stderr); + return EXIT_FAILURE; + } + + eina_init(); + ret = eina_xattr_set(argv[2], argv[3], argv[4], strlen(argv[4]), 0); + + printf("set xattr '%s=%s' on '%s': %s\n", + argv[3], argv[4], argv[2], ret ? "success" : "failure"); + + eina_shutdown(); + } + else + fprintf(stderr, "ERROR: unknown command '%s'\n", argv[1]); + + return 0; +} diff --git a/src/examples/eina/eina_xattr_02.c b/src/examples/eina/eina_xattr_02.c new file mode 100644 index 0000000000..4c4264da1f --- /dev/null +++ b/src/examples/eina/eina_xattr_02.c @@ -0,0 +1,24 @@ +//Compile with: +//gcc -g eina_xattr_02.c -o eina_xattr_02 `pkg-config --cflags --libs eina` + +#include + +int +main(int argc, char **argv) +{ + Eina_Bool ret; + + if (argc != 3) + { + fprintf(stderr, "ERROR: incorrect usage.\nUsage: %s \n", + argv[0]); + return EXIT_FAILURE; + } + + eina_init(); + ret = eina_xattr_copy(argv[1], argv[2]); + printf("copied xattrs from '%s' to '%s': %s\n", + argv[1], argv[2], ret ? "success" : "failure"); + eina_shutdown(); + return 0; +} diff --git a/src/lib/eina/eina_xattr.c b/src/lib/eina/eina_xattr.c index 4dcda3e465..e1fac0fa21 100644 --- a/src/lib/eina/eina_xattr.c +++ b/src/lib/eina/eina_xattr.c @@ -352,7 +352,7 @@ eina_xattr_get(const char *file, const char *attribute, ssize_t *size) EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL); - EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(size, NULL); *size = getxattr(file, attribute, NULL, 0); /* Size should be less than 2MB (already huge in my opinion) */ @@ -382,6 +382,44 @@ eina_xattr_get(const char *file, const char *attribute, ssize_t *size) #endif } +EAPI void * +eina_xattr_fd_get(int fd, const char *attribute, ssize_t *size) +{ +#ifdef HAVE_XATTR + char *ret = NULL; + ssize_t tmp; + + EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(size, NULL); + + *size = fgetxattr(fd, 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 + 1); + if (!ret) goto on_error; + + tmp = fgetxattr(fd, attribute, ret, *size); + if (tmp != *size) + goto on_error; + ret[tmp] = '\0'; + + return ret; + + on_error: + free(ret); + *size = 0; + return NULL; +#else + EINA_SAFETY_ON_NULL_RETURN_VAL(size, NULL); + *size = 0; + return NULL; + (void)fd; + (void)attribute; +#endif +} + EAPI Eina_Bool eina_xattr_set(const char *file, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags) { @@ -415,6 +453,65 @@ eina_xattr_set(const char *file, const char *attribute, const void *data, ssize_ #endif } +EAPI Eina_Bool +eina_xattr_fd_set(int fd, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags) +{ +#ifdef HAVE_XATTR + int iflags; + + EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL(!(length > 0 && length < 2 * 1024 * 1024), 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 (fsetxattr(fd, attribute, data, length, iflags)) + return EINA_FALSE; + return EINA_TRUE; +#else + return EINA_FALSE; + (void)fd; + (void)attribute; + (void)data; + (void)length; + (void)flags; +#endif +} + +EAPI Eina_Bool +eina_xattr_del(const char *file, const char *attribute) +{ +#ifdef HAVE_XATTR + EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, EINA_FALSE); + return removexattr(file, attribute) == 0; +#else + return EINA_FALSE; + (void)file; + (void)attribute; +#endif +} + +EAPI Eina_Bool +eina_xattr_fd_del(int fd, const char *attribute) +{ +#ifdef HAVE_XATTR + EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, EINA_FALSE); + return fremovexattr(fd, attribute) == 0; +#else + return EINA_FALSE; + (void)fd; + (void)attribute; +#endif +} + EAPI Eina_Bool eina_xattr_string_set(const char *file, const char *attribute, const char *data, Eina_Xattr_Flags flags) { @@ -501,3 +598,88 @@ eina_xattr_int_get(const char *file, const char *attribute, int *value) return result; } + +EAPI Eina_Bool +eina_xattr_copy(const char *src, const char *dst) +{ +#ifdef HAVE_XATTR + int sfd, dfd; + Eina_Bool ret = EINA_FALSE; + + EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE); + + sfd = open(src, O_RDONLY); + EINA_SAFETY_ON_TRUE_GOTO(sfd < 0, s_end); + + dfd = open(dst, O_RDWR); + EINA_SAFETY_ON_TRUE_GOTO(dfd < 0, d_end); + + ret = eina_xattr_fd_copy(sfd, dfd); + + close(dfd); + d_end: + close(sfd); + s_end: + return ret; + +#else + return EINA_FALSE; + (void)src; + (void)dst; +#endif +} + +EAPI Eina_Bool +eina_xattr_fd_copy(int src, int dst) +{ +#ifdef HAVE_XATTR + char *buf, *attr; + ssize_t i, length; + Eina_Bool ret; + + length = flistxattr(src, NULL, 0); + if (length == 0) return EINA_TRUE; + EINA_SAFETY_ON_TRUE_RETURN_VAL(length < 0, EINA_FALSE); + + buf = malloc(length); + EINA_SAFETY_ON_NULL_RETURN_VAL(buf, EINA_FALSE); + + attr = buf; + length = flistxattr(src, attr, length); + ret = EINA_TRUE; + for (i = 0; i < length; i += strlen(attr) + 1, attr += strlen(attr) + 1) + { + ssize_t attr_length; + void *value; + + attr_length = fgetxattr(src, attr, NULL, 0); + EINA_SAFETY_ON_TRUE_GOTO(attr_length < 0, attr_error); + + if (attr_length == 0) + value = NULL; + else + { + value = malloc(attr_length); + EINA_SAFETY_ON_NULL_GOTO(value, attr_error); + + attr_length = fgetxattr(src, attr, value, attr_length); + } + + fsetxattr(dst, attr, value, attr_length, 0); + free(value); + continue; + + attr_error: + ret = EINA_FALSE; + } + + free(buf); + return ret; + +#else + return EINA_FALSE; + (void)src; + (void)dst; +#endif +} diff --git a/src/lib/eina/eina_xattr.h b/src/lib/eina/eina_xattr.h index e4db4c5a24..b37262ee31 100644 --- a/src/lib/eina/eina_xattr.h +++ b/src/lib/eina/eina_xattr.h @@ -59,7 +59,7 @@ struct _Eina_Xattr * * @since 1.1 */ -EAPI Eina_Iterator *eina_xattr_ls(const char *file); +EAPI Eina_Iterator *eina_xattr_ls(const char *file) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; /** * @brief Get an iterator that list all extended attribute value related to a fd. @@ -72,7 +72,7 @@ EAPI Eina_Iterator *eina_xattr_ls(const char *file); * * @since 1.2 */ -EAPI Eina_Iterator *eina_xattr_value_ls(const char *file); +EAPI Eina_Iterator *eina_xattr_value_ls(const char *file) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; /** * @brief Get an iterator that list all extended attribute related to a fd. @@ -85,7 +85,7 @@ EAPI Eina_Iterator *eina_xattr_value_ls(const char *file); * * @since 1.2 */ -EAPI Eina_Iterator *eina_xattr_fd_ls(int fd); +EAPI Eina_Iterator *eina_xattr_fd_ls(int fd) EINA_WARN_UNUSED_RESULT; /** * @brief Get an iterator that list all extended attribute value related to a fd. @@ -98,7 +98,27 @@ EAPI Eina_Iterator *eina_xattr_fd_ls(int fd); * * @since 1.2 */ -EAPI Eina_Iterator *eina_xattr_value_fd_ls(int fd); +EAPI Eina_Iterator *eina_xattr_value_fd_ls(int fd) EINA_WARN_UNUSED_RESULT; + +/** + * @brief Copy the extended attribute from one file to another. + * @param src source file to use as input. + * @param dst destination file to use as output. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @see eina_xattr_fd_copy() + * @since 1.8 + */ +EAPI Eina_Bool eina_xattr_copy(const char *src, const char *dst) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Copy the extended attribute from one file descriptor to another. + * @param src source file descriptor to use as input. + * @param dst destination file descriptor to use as output. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @see eina_xattr_copy() + * @since 1.8 + */ +EAPI Eina_Bool eina_xattr_fd_copy(int src, int dst); /** * @brief Retrieve an extended attribute from a file. @@ -112,7 +132,21 @@ EAPI Eina_Iterator *eina_xattr_value_fd_ls(int fd); * * @since 1.1 */ -EAPI void *eina_xattr_get(const char *file, const char *attribute, ssize_t *size); +EAPI void *eina_xattr_get(const char *file, const char *attribute, ssize_t *size) EINA_ARG_NONNULL(1, 2, 3) EINA_WARN_UNUSED_RESULT; + +/** + * @brief Retrieve an extended attribute from a file descriptor. + * + * @param fd The file descriptor to retrieve the extended attribute from. + * @param attribute 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 @c NULL and *size will be @c 0 if it fails. + * + * @since 1.8 + */ +EAPI void *eina_xattr_fd_get(int fd, const char *attribute, ssize_t *size) EINA_ARG_NONNULL(2, 3) EINA_WARN_UNUSED_RESULT; /** * @brief Set an extended attribute on a file. @@ -126,7 +160,44 @@ EAPI void *eina_xattr_get(const char *file, const char *attribute, ssize_t *size * * @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); +EAPI Eina_Bool eina_xattr_set(const char *file, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags) EINA_ARG_NONNULL(1, 2, 3); + +/** + * @brief Set an extended attribute on a file descriptor. + * + * @param fd The file descriptor 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.8 + */ +EAPI Eina_Bool eina_xattr_fd_set(int fd, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags) EINA_ARG_NONNULL(2, 3); + + +/** + * @brief Delete (remove) an extended attribute from a file. + * + * @param file The file to del the extended attribute from. + * @param attribute The attribute to del. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * @since 1.8 + */ +EAPI Eina_Bool eina_xattr_del(const char *file, const char *attribute) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Delete (remove) an extended attribute from a file descriptor. + * + * @param fd The file descriptor to del the extended attribute from. + * @param attribute The attribute to del. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * @since 1.8 + */ +EAPI Eina_Bool eina_xattr_fd_del(int fd, const char *attribute) EINA_ARG_NONNULL(2); /** * @brief Set a string as a extended attribute properties.