write extended attributes by using fsetxattr

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 caused by moved or deleted files.
This commit is contained in:
Stefan Tomanek 2010-11-07 16:54:49 +01:00 committed by Daniel Stenberg
parent 892cacef43
commit f1db21218b
5 changed files with 54 additions and 53 deletions

View File

@ -2349,7 +2349,7 @@ CURL_CHECK_FUNC_LOCALTIME_R
CURL_CHECK_FUNC_MEMRCHR CURL_CHECK_FUNC_MEMRCHR
CURL_CHECK_FUNC_POLL CURL_CHECK_FUNC_POLL
CURL_CHECK_FUNC_SETSOCKOPT CURL_CHECK_FUNC_SETSOCKOPT
CURL_CHECK_FUNC_SETXATTR CURL_CHECK_FUNC_FSETXATTR
CURL_CHECK_FUNC_SIGACTION CURL_CHECK_FUNC_SIGACTION
CURL_CHECK_FUNC_SIGINTERRUPT CURL_CHECK_FUNC_SIGINTERRUPT
CURL_CHECK_FUNC_SIGNAL CURL_CHECK_FUNC_SIGNAL

View File

@ -5924,86 +5924,86 @@ AC_DEFUN([CURL_CHECK_FUNC_WRITEV], [
fi fi
]) ])
dnl CURL_CHECK_FUNC_SETXATTR dnl CURL_CHECK_FUNC_FSETXATTR
dnl ------------------------------------------------- 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 can be compiled. If all of these are true, and
dnl usage has not been previously disallowed with dnl usage has not been previously disallowed with
dnl shell variable curl_disallow_setxattr, then dnl shell variable curl_disallow_fsetxattr, then
dnl HAVE_SETXATTR will be defined. 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 AC_REQUIRE([CURL_INCLUDES_SYS_XATTR])dnl
# #
tst_links_setxattr="unknown" tst_links_fsetxattr="unknown"
tst_proto_setxattr="unknown" tst_proto_fsetxattr="unknown"
tst_compi_setxattr="unknown" tst_compi_fsetxattr="unknown"
tst_allow_setxattr="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_LINK_IFELSE([
AC_LANG_FUNC_LINK_TRY([setxattr]) AC_LANG_FUNC_LINK_TRY([fsetxattr])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
tst_links_setxattr="yes" tst_links_fsetxattr="yes"
],[ ],[
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
tst_links_setxattr="no" tst_links_fsetxattr="no"
]) ])
# #
if test "$tst_links_setxattr" = "yes"; then if test "$tst_links_fsetxattr" = "yes"; then
AC_MSG_CHECKING([if setxattr is prototyped]) AC_MSG_CHECKING([if fsetxattr is prototyped])
AC_EGREP_CPP([setxattr],[ AC_EGREP_CPP([fsetxattr],[
$curl_includes_sys_xattr $curl_includes_sys_xattr
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
tst_proto_setxattr="yes" tst_proto_fsetxattr="yes"
],[ ],[
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
tst_proto_setxattr="no" tst_proto_fsetxattr="no"
]) ])
fi fi
# #
if test "$tst_proto_setxattr" = "yes"; then if test "$tst_proto_fsetxattr" = "yes"; then
AC_MSG_CHECKING([if setxattr is compilable]) AC_MSG_CHECKING([if fsetxattr is compilable])
AC_COMPILE_IFELSE([ AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[ AC_LANG_PROGRAM([[
$curl_includes_sys_xattr $curl_includes_sys_xattr
]],[[ ]],[[
if(0 != setxattr(0, 0, 0, 0, 0)) if(0 != fsetxattr("", "", "", 0, 0))
return 1; return 1;
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
tst_compi_setxattr="yes" tst_compi_fsetxattr="yes"
],[ ],[
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
tst_compi_setxattr="no" tst_compi_fsetxattr="no"
]) ])
fi fi
# #
if test "$tst_compi_setxattr" = "yes"; then if test "$tst_compi_fsetxattr" = "yes"; then
AC_MSG_CHECKING([if setxattr usage allowed]) AC_MSG_CHECKING([if fsetxattr usage allowed])
if test "x$curl_disallow_setxattr" != "xyes"; then if test "x$curl_disallow_fsetxattr" != "xyes"; then
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
tst_allow_setxattr="yes" tst_allow_fsetxattr="yes"
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
tst_allow_setxattr="no" tst_allow_fsetxattr="no"
fi fi
fi fi
# #
AC_MSG_CHECKING([if setxattr might be used]) AC_MSG_CHECKING([if fsetxattr might be used])
if test "$tst_links_setxattr" = "yes" && if test "$tst_links_fsetxattr" = "yes" &&
test "$tst_proto_setxattr" = "yes" && test "$tst_proto_fsetxattr" = "yes" &&
test "$tst_compi_setxattr" = "yes" && test "$tst_compi_fsetxattr" = "yes" &&
test "$tst_allow_setxattr" = "yes"; then test "$tst_allow_fsetxattr" = "yes"; then
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED(HAVE_SETXATTR, 1, AC_DEFINE_UNQUOTED(HAVE_FSETXATTR, 1,
[Define to 1 if you have the setxattr function.]) [Define to 1 if you have the fsetxattr function.])
ac_cv_func_setxattr="yes" ac_cv_func_fsetxattr="yes"
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
ac_cv_func_setxattr="no" ac_cv_func_fsetxattr="no"
fi fi
]) ])

View File

@ -5633,9 +5633,17 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
} }
} }
} }
if(outfile && !curlx_strequal(outfile, "-") && outs.stream) { if(outfile && !curlx_strequal(outfile, "-") && outs.stream) {
int rc = fclose(outs.stream); int rc;
if(config->xattr) {
rc = fwrite_xattr(curl, fileno(outs.stream) );
if(rc)
warnf(config, "Error setting extended attributes: %s\n",
strerror(errno) );
}
rc = fclose(outs.stream);
if(!res && rc) { if(!res && rc) {
/* something went wrong in the writing process */ /* something went wrong in the writing process */
res = CURLE_WRITE_ERROR; res = CURLE_WRITE_ERROR;
@ -5643,13 +5651,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 #ifdef HAVE_UTIME
/* Important that we set the time _after_ the file has been /* Important that we set the time _after_ the file has been
closed, as is done above here */ closed, as is done above here */

View File

@ -25,7 +25,7 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "xattr.h" #include "xattr.h"
#ifdef HAVE_SETXATTR #ifdef HAVE_FSETXATTR
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include <sys/xattr.h> /* include header from libc, not from libattr */ #include <sys/xattr.h> /* include header from libc, not from libattr */
@ -46,7 +46,7 @@ static const struct xattr_mapping {
/* store metadata from the curl request alongside the downloaded /* store metadata from the curl request alongside the downloaded
* file using extended attributes * file using extended attributes
*/ */
int write_xattr(CURL *curl, const char *filename) int fwrite_xattr(CURL *curl, int fd)
{ {
int i = 0; int i = 0;
int err = 0; int err = 0;
@ -55,17 +55,17 @@ int write_xattr(CURL *curl, const char *filename)
char *value = NULL; char *value = NULL;
CURLcode rc = curl_easy_getinfo(curl, mappings[i].info, &value); CURLcode rc = curl_easy_getinfo(curl, mappings[i].info, &value);
if ( rc == CURLE_OK && value ) { if ( rc == CURLE_OK && value ) {
err = setxattr( filename, mappings[i].attr, value, strlen(value), 0 ); err = fsetxattr( fd, mappings[i].attr, value, strlen(value), 0 );
} }
i++; i++;
} }
return err; return err;
} }
#else #else
int write_xattr(CURL *curl, const char *filename) int fwrite_xattr(CURL *curl, int fd)
{ {
(void)curl; (void)curl;
(void)filename; (void)fd;
return 0; return 0;
} }
#endif #endif

View File

@ -21,6 +21,6 @@
* KIND, either express or implied. * KIND, either express or implied.
* *
***************************************************************************/ ***************************************************************************/
int write_xattr( CURL *curl, const char *filename ); int fwrite_xattr(CURL *curl, int fd);
#endif #endif