]> granicus.if.org Git - curl/commitdiff
write extended attributes by using fsetxattr
authorStefan Tomanek <stefan.tomanek@wertarbyte.de>
Sun, 7 Nov 2010 15:54:49 +0000 (16:54 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 10 Nov 2010 09:43:05 +0000 (10:43 +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 caused by moved or deleted files.

configure.ac
m4/curl-functions.m4
src/main.c
src/xattr.c
src/xattr.h

index 893e53c0c4e029d79be49efc2aeee354efe8e4ba..cc2b6f4d27783f8bc40515ba639fba41afac59ee 100644 (file)
@@ -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
index ca5b86fc37d428a27087cfa1308835abfd926794..7f7cb8610e28855b16bb07a7cdfc90aa85460e26 100644 (file)
@@ -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, 0, 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
 ])
index deca6c97969014e5245c2d9e20318ff8508c6169..2f81ef4e8d1241b32bde1fbd15fad14a4ebc43e3 100644 (file)
@@ -5633,9 +5633,17 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
             }
           }
         }
-
         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) {
             /* something went wrong in the writing process */
             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
         /* Important that we set the time _after_ the file has been
            closed, as is done above here */
index e0350968050581869a4dff7be57c3d620ffb90f5..a770405c9fd7f84eb52afb73cb5c53c8ae0fb498 100644 (file)
@@ -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 const 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;
     CURLcode rc = curl_easy_getinfo(curl, mappings[i].info, &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++;
   }
   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
index df62066c87969ad319f87ae59ea740e343166737..fea98f188f1d2ac0849299339d1babf7708da565 100644 (file)
@@ -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