curl-users
[PATCH] write extended attributes by using fsetxattr
From: Stefan Tomanek <stefan.tomanek_at_wertarbyte.de>
Date: Mon, 8 Nov 2010 21:08:50 +0100
Date: Mon, 8 Nov 2010 21:08:50 +0100
Instead of reopening the downloaded file, fsetxattr uses the (already
open) file descriptor to attach extended attributes. This makes the
procedure more robust against errors from moved or deleted files.
Signed-off-by: Stefan Tomanek <stefan.tomanek_at_wertarbyte.de>
--- configure.ac | 2 +- m4/curl-functions.m4 | 74 +++++++++++++++++++++++++------------------------- src/main.c | 15 +++++----- src/xattr.c | 10 +++--- src/xattr.h | 2 +- 5 files changed, 51 insertions(+), 52 deletions(-) diff --git a/configure.ac b/configure.ac index 893e53c..cc2b6f4 100644 --- a/configure.ac +++ b/configure.ac @@ -2349,7 +2349,7 @@ CURL_CHECK_FUNC_LOCALTIME_R CURL_CHECK_FUNC_MEMRCHR CURL_CHECK_FUNC_POLL CURL_CHECK_FUNC_SETSOCKOPT -CURL_CHECK_FUNC_SETXATTR +CURL_CHECK_FUNC_FSETXATTR CURL_CHECK_FUNC_SIGACTION CURL_CHECK_FUNC_SIGINTERRUPT CURL_CHECK_FUNC_SIGNAL diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4 index 1bbd330..73ebe56 100644 --- a/m4/curl-functions.m4 +++ b/m4/curl-functions.m4 @@ -5924,86 +5924,86 @@ AC_DEFUN([CURL_CHECK_FUNC_WRITEV], [ fi ]) -dnl CURL_CHECK_FUNC_SETXATTR +dnl CURL_CHECK_FUNC_FSETXATTR dnl ------------------------------------------------- -dnl Verify if setxattr is available, prototyped, and +dnl Verify if fsetxattr is available, prototyped, and dnl can be compiled. If all of these are true, and dnl usage has not been previously disallowed with -dnl shell variable curl_disallow_setxattr, then -dnl HAVE_SETXATTR will be defined. +dnl shell variable curl_disallow_fsetxattr, then +dnl HAVE_FSETXATTR will be defined. -AC_DEFUN([CURL_CHECK_FUNC_SETXATTR], [ +AC_DEFUN([CURL_CHECK_FUNC_FSETXATTR], [ AC_REQUIRE([CURL_INCLUDES_SYS_XATTR])dnl # - tst_links_setxattr="unknown" - tst_proto_setxattr="unknown" - tst_compi_setxattr="unknown" - tst_allow_setxattr="unknown" + tst_links_fsetxattr="unknown" + tst_proto_fsetxattr="unknown" + tst_compi_fsetxattr="unknown" + tst_allow_fsetxattr="unknown" # - AC_MSG_CHECKING([if setxattr can be linked]) + AC_MSG_CHECKING([if fsetxattr can be linked]) AC_LINK_IFELSE([ - AC_LANG_FUNC_LINK_TRY([setxattr]) + AC_LANG_FUNC_LINK_TRY([fsetxattr]) ],[ AC_MSG_RESULT([yes]) - tst_links_setxattr="yes" + tst_links_fsetxattr="yes" ],[ AC_MSG_RESULT([no]) - tst_links_setxattr="no" + tst_links_fsetxattr="no" ]) # - if test "$tst_links_setxattr" = "yes"; then - AC_MSG_CHECKING([if setxattr is prototyped]) - AC_EGREP_CPP([setxattr],[ + if test "$tst_links_fsetxattr" = "yes"; then + AC_MSG_CHECKING([if fsetxattr is prototyped]) + AC_EGREP_CPP([fsetxattr],[ $curl_includes_sys_xattr ],[ AC_MSG_RESULT([yes]) - tst_proto_setxattr="yes" + tst_proto_fsetxattr="yes" ],[ AC_MSG_RESULT([no]) - tst_proto_setxattr="no" + tst_proto_fsetxattr="no" ]) fi # - if test "$tst_proto_setxattr" = "yes"; then - AC_MSG_CHECKING([if setxattr is compilable]) + if test "$tst_proto_fsetxattr" = "yes"; then + AC_MSG_CHECKING([if fsetxattr is compilable]) AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ $curl_includes_sys_xattr ]],[[ - if(0 != setxattr("", "", "", 0, 0)) + if(0 != fsetxattr("", "", "", 0, 0)) return 1; ]]) ],[ AC_MSG_RESULT([yes]) - tst_compi_setxattr="yes" + tst_compi_fsetxattr="yes" ],[ AC_MSG_RESULT([no]) - tst_compi_setxattr="no" + tst_compi_fsetxattr="no" ]) fi # - if test "$tst_compi_setxattr" = "yes"; then - AC_MSG_CHECKING([if setxattr usage allowed]) - if test "x$curl_disallow_setxattr" != "xyes"; then + if test "$tst_compi_fsetxattr" = "yes"; then + AC_MSG_CHECKING([if fsetxattr usage allowed]) + if test "x$curl_disallow_fsetxattr" != "xyes"; then AC_MSG_RESULT([yes]) - tst_allow_setxattr="yes" + tst_allow_fsetxattr="yes" else AC_MSG_RESULT([no]) - tst_allow_setxattr="no" + tst_allow_fsetxattr="no" fi fi # - AC_MSG_CHECKING([if setxattr might be used]) - if test "$tst_links_setxattr" = "yes" && - test "$tst_proto_setxattr" = "yes" && - test "$tst_compi_setxattr" = "yes" && - test "$tst_allow_setxattr" = "yes"; then + AC_MSG_CHECKING([if fsetxattr might be used]) + if test "$tst_links_fsetxattr" = "yes" && + test "$tst_proto_fsetxattr" = "yes" && + test "$tst_compi_fsetxattr" = "yes" && + test "$tst_allow_fsetxattr" = "yes"; then AC_MSG_RESULT([yes]) - AC_DEFINE_UNQUOTED(HAVE_SETXATTR, 1, - [Define to 1 if you have the setxattr function.]) - ac_cv_func_setxattr="yes" + AC_DEFINE_UNQUOTED(HAVE_FSETXATTR, 1, + [Define to 1 if you have the fsetxattr function.]) + ac_cv_func_fsetxattr="yes" else AC_MSG_RESULT([no]) - ac_cv_func_setxattr="no" + ac_cv_func_fsetxattr="no" fi ]) diff --git a/src/main.c b/src/main.c index deca6c9..92e712d 100644 --- a/src/main.c +++ b/src/main.c @@ -5633,8 +5633,14 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) } } } - if(outfile && !curlx_strequal(outfile, "-") && outs.stream) { + if(config->xattr) { + int err = fwrite_xattr(curl, fileno(outs.stream) ); + if(err) + warnf( config, "Error setting extended attributes: %s\n", + strerror(errno) ); + } + int rc = fclose(outs.stream); if(!res && rc) { /* something went wrong in the writing process */ @@ -5643,13 +5649,6 @@ operate(struct Configurable *config, int argc, argv_item_t argv[]) } } - if(config->xattr && outs.filename) { - int err = write_xattr(curl, outs.filename ); - if(err) - warnf( config, "Error setting extended attributes: %s\n", - strerror(errno) ); - } - #ifdef HAVE_UTIME /* Important that we set the time _after_ the file has been closed, as is done above here */ diff --git a/src/xattr.c b/src/xattr.c index eb244f8..28db93c 100644 --- a/src/xattr.c +++ b/src/xattr.c @@ -25,7 +25,7 @@ #include <curl/curl.h> #include "xattr.h" -#ifdef HAVE_SETXATTR +#ifdef HAVE_FSETXATTR #include <sys/types.h> #include <string.h> #include <sys/xattr.h> /* include header from libc, not from libattr */ @@ -46,7 +46,7 @@ static struct xattr_mapping { /* store metadata from the curl request alongside the downloaded * file using extended attributes */ -int write_xattr(CURL *curl, const char *filename) +int fwrite_xattr(CURL *curl, int fd) { int i = 0; int err = 0; @@ -55,17 +55,17 @@ int write_xattr(CURL *curl, const char *filename) char *value = NULL; curl_easy_getinfo(curl, mappings[i].info, &value); if (value) { - err = setxattr( filename, mappings[i].attr, value, strlen(value), 0 ); + err = fsetxattr( fd, mappings[i].attr, value, strlen(value), 0 ); } i++; } return err; } #else -int write_xattr(CURL *curl, const char *filename) +int fwrite_xattr(CURL *curl, int fd) { (void)curl; - (void)filename; + (void)fd; return 0; } #endif diff --git a/src/xattr.h b/src/xattr.h index df62066..fea98f1 100644 --- a/src/xattr.h +++ b/src/xattr.h @@ -21,6 +21,6 @@ * KIND, either express or implied. * ***************************************************************************/ -int write_xattr( CURL *curl, const char *filename ); +int fwrite_xattr(CURL *curl, int fd); #endif -- 1.7.2.3 ------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-users FAQ: http://curl.haxx.se/docs/faq.html Etiquette: http://curl.haxx.se/mail/etiquette.htmlReceived on 2010-11-08