efl/eio: use eina_file_copy()
authorGustavo Sverzut Barbieri <barbieri@gmail.com>
Mon, 31 Dec 2012 23:45:24 +0000 (23:45 +0000)
committerGustavo Sverzut Barbieri <barbieri@gmail.com>
Mon, 31 Dec 2012 23:45:24 +0000 (23:45 +0000)
SVN revision: 81944

configure.ac
src/examples/eio/Makefile.am
src/examples/eio/eio_file_copy.c [new file with mode: 0644]
src/lib/eio/eio_file.c

index 1c5f93f..be92992 100644 (file)
@@ -810,7 +810,7 @@ AC_DEFINE_IF([HAVE_DIRENT_H], [test "x${have_dirent}" = "xyes"],
 
 ### Checks for library functions
 
-EFL_CHECK_FUNCS([EINA], [dlopen dladdr iconv shm_open setxattr])
+EFL_CHECK_FUNCS([EINA], [dlopen dladdr iconv shm_open splice setxattr])
 
 enable_log="no"
 if test "x${efl_func_fnmatch}" = "xyes" && test "x${want_log}" = "xyes" ; then
@@ -3055,7 +3055,6 @@ EFL_ADD_LIBS([EIO], [-lm])
 ### Checks for linker characteristics
 
 ### Checks for library functions
-EFL_CHECK_FUNCS([EIO], [splice setxattr])
 
 EFL_LIB_END([Eio])
 #### End of Eio
index ad4f901..950f1ec 100644 (file)
@@ -12,7 +12,9 @@ AM_CPPFLAGS = \
 -I$(top_builddir)/src/lib/ecore \
 -I$(top_builddir)/src/lib/eio
 
-EXTRA_PROGRAMS = eio_file_ls
+EXTRA_PROGRAMS = \
+eio_file_ls \
+eio_file_copy
 
 eio_file_ls_SOURCES = eio_file_ls.c
 eio_file_ls_LDADD = \
@@ -23,8 +25,18 @@ $(top_builddir)/src/lib/eet/libeet.la \
 $(top_builddir)/src/lib/eina/libeina.la \
 @EIO_LDFLAGS@
 
+eio_file_copy_SOURCES = eio_file_copy.c
+eio_file_copy_LDADD = \
+$(top_builddir)/src/lib/eio/libeio.la \
+$(top_builddir)/src/lib/eo/libeo.la \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/eet/libeet.la \
+$(top_builddir)/src/lib/eina/libeina.la \
+@EIO_LDFLAGS@
+
 SRCS = \
-eio_file_ls
+eio_file_ls.c \
+eio_file_copy.c
 
 examples: $(EXTRA_PROGRAMS)
 
diff --git a/src/examples/eio/eio_file_copy.c b/src/examples/eio/eio_file_copy.c
new file mode 100644 (file)
index 0000000..7704cfc
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+  * Compile with gcc -o eio_file_copy eio_file_copy.c `pkg-config --cflags --libs ecore eio`
+  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <Eio.h>
+#include <Ecore.h>
+
+static void
+_progress_cb(void *data EINA_UNUSED, Eio_File *handle EINA_UNUSED, const Eio_Progress *info)
+{
+   printf("progress: %5lld/%lld (%3.0f%%)\n", info->current, info->max,
+          info->percent);
+}
+
+static void
+_done_cb(void *data EINA_UNUSED, Eio_File *handle EINA_UNUSED)
+{
+   puts("Successfully finished copy");
+   ecore_main_loop_quit();
+}
+
+static void
+_error_cb(void *data EINA_UNUSED, Eio_File *handle EINA_UNUSED, int error)
+{
+   fprintf(stderr, "Something wrong has happend:%s\n", strerror(error));
+   ecore_main_loop_quit();
+}
+
+int
+main(int argc, char **argv)
+{
+   if (argc != 3)
+     {
+        fprintf(stderr, "Usage: %s <src> <dst>\n", argv[0]);
+        return  EXIT_FAILURE;
+     }
+
+   ecore_init();
+   eio_init();
+
+   eio_file_copy(argv[1], argv[2], _progress_cb, _done_cb, _error_cb, NULL);
+
+   ecore_main_loop_begin();
+
+   eio_shutdown();
+   ecore_shutdown();
+
+   return 0;
+}
index 50a8be2..62694a5 100644 (file)
 #include "eio_private.h"
 #include "Eio.h"
 
-#ifdef HAVE_XATTR
-# include <sys/xattr.h>
-#endif
-
 /*============================================================================*
  *                                  Local                                     *
  *============================================================================*/
@@ -244,170 +240,10 @@ _eio_file_direct_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_
      }
 }
 
-static void
-_eio_eina_file_copy_xattr(Ecore_Thread *thread EINA_UNUSED,
-                         Eio_File_Progress *op EINA_UNUSED,
-                         Eina_File *f, int out)
-{
-   Eina_Iterator *it;
-   Eina_Xattr *attr;
-
-   it = eina_file_xattr_value_get(f);
-   EINA_ITERATOR_FOREACH(it, attr)
-     {
-#ifdef HAVE_XATTR
-        fsetxattr(out, attr->name, attr->value, attr->length, 0);
-#endif
-     }
-   eina_iterator_free(it);
-}
-
-#ifdef HAVE_XATTR
-static void
-_eio_file_copy_xattr(Ecore_Thread *thread EINA_UNUSED,
-                     Eio_File_Progress *op EINA_UNUSED,
-                     int in, int out)
-{
-   char *tmp;
-   ssize_t length;
-   ssize_t i;
-
-   length = flistxattr(in, NULL, 0);
-
-   if (length <= 0) return ;
-
-   tmp = alloca(length);
-   length = flistxattr(in, tmp, length);
-
-   for (i = 0; i < length; i += strlen(tmp) + 1)
-     {
-        ssize_t attr_length;
-        void *value;
-
-        attr_length = fgetxattr(in, tmp, NULL, 0);
-        if (!attr_length) continue ;
-
-        value = malloc(attr_length);
-        if (!value) continue ;
-        attr_length = fgetxattr(in, tmp, value, attr_length);
-
-        if (attr_length > 0)
-          fsetxattr(out, tmp, value, attr_length, 0);
-
-        free(value);
-     }
-}
-#endif
-
-static Eina_Bool
-_eio_file_write(int fd, void *mem, ssize_t length)
-{
-   ssize_t count;
-
-   if (length == 0) return EINA_TRUE;
-
-   count = write(fd, mem, length);
-   if (count != length) return EINA_FALSE;
-   return EINA_TRUE;
-}
-
 #ifndef MAP_HUGETLB
 # define MAP_HUGETLB 0
 #endif
 
-static Eina_Bool
-_eio_file_copy_mmap(Ecore_Thread *thread, Eio_File_Progress *op, Eina_File *f, int out)
-{
-   char *m = MAP_FAILED;
-   long long i;
-   long long size;
-
-   size = eina_file_size_get(f);
-
-   for (i = 0; i < size; i += EIO_PACKET_SIZE * EIO_PACKET_COUNT)
-     {
-       int j;
-       int k;
-       int c;
-
-        m = eina_file_map_new(f, EINA_FILE_SEQUENTIAL,
-                              i, EIO_PACKET_SIZE * EIO_PACKET_COUNT);
-       if (!m)
-         goto on_error;
-
-       c = size - i;
-       if (c - EIO_PACKET_SIZE * EIO_PACKET_COUNT > 0)
-         c = EIO_PACKET_SIZE * EIO_PACKET_COUNT;
-       else
-         c = size - i;
-
-       for (j = EIO_PACKET_SIZE, k = 0; j < c; k = j, j += EIO_PACKET_SIZE)
-         {
-            if (!_eio_file_write(out, m + k, EIO_PACKET_SIZE))
-              goto on_error;
-
-            eio_progress_send(thread, op, i + j, size);
-         }
-
-       if (!_eio_file_write(out, m + k, c - k))
-         goto on_error;
-
-        if (eina_file_map_faulted(f, m))
-          goto on_error;
-
-       eio_progress_send(thread, op, i + c, size);
-
-        eina_file_map_free(f, m);
-       m = NULL;
-
-       if (ecore_thread_check(thread))
-          goto on_error;
-     }
-
-   return EINA_TRUE;
-
- on_error:
-   if (m != NULL) eina_file_map_free(f, m);
-   return EINA_FALSE;
-}
-
-#ifdef HAVE_SPLICE
-static int
-_eio_file_copy_splice(Ecore_Thread *thread, Eio_File_Progress *op, int in, int out, long long size)
-{
-   int result = 0;
-   long long count;
-   long long i;
-   int pipefd[2];
-
-   if (pipe(pipefd) < 0)
-     return -1;
-
-   for (i = 0; i < size; i += count)
-     {
-       count = splice(in, 0, pipefd[1], NULL, EIO_PACKET_SIZE * EIO_PACKET_COUNT, SPLICE_F_MORE | SPLICE_F_MOVE);
-       if (count < 0) goto on_error;
-
-       count = splice(pipefd[0], NULL, out, 0, count, SPLICE_F_MORE | SPLICE_F_MOVE);
-       if (count < 0) goto on_error;
-
-       eio_progress_send(thread, op, i, size);
-
-       if (ecore_thread_check(thread))
-          goto on_error;
-     }
-
-   result = 1;
-
- on_error:
-   if (result != 1 && (errno == EBADF || errno == EINVAL)) result = -1;
-   close(pipefd[0]);
-   close(pipefd[1]);
-
-   return result;
-}
-#endif
-
 static void
 _eio_file_copy_heavy(void *data, Ecore_Thread *thread)
 {
@@ -600,106 +436,35 @@ eio_progress_cb(Eio_Progress *progress, Eio_File_Progress *op)
    eio_progress_free(progress);
 }
 
-Eina_Bool
-eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy)
+static Eina_Bool
+_eio_file_copy_progress(void *data, unsigned long long done, unsigned long long total)
 {
-   Eina_File *f;
-#ifdef HAVE_SPLICE
-   struct stat buf;
-   int in = -1;
-#endif
-   mode_t md;
-   int result = -1;
-   int out = -1;
-
-#ifdef HAVE_SPLICE
-   in = open(copy->source, O_RDONLY);
-   if (in < 0)
-     {
-       eio_file_thread_error(&copy->common, thread);
-       return EINA_FALSE;
-     }
-
-   /*
-     As we need file size for progression information and both copy method
-     call fstat (better than stat as it avoid race condition).
-    */
-   if (fstat(in, &buf) < 0)
-     goto on_error;
+   void **ctx = data;
+   Ecore_Thread *thread = ctx[0];
+   Eio_File_Progress *copy = ctx[1];
 
-   md = buf.st_mode;
-#endif
+   eio_progress_send(thread, copy, done, total);
 
-   /* open write */
-   out = open(copy->dest, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
-   if (out < 0)
-     goto on_error;
-
-#ifdef HAVE_SPLICE
-   /* fast file copy code using Linux splice API */
-   result = _eio_file_copy_splice(thread, copy, in, out, buf.st_size);
-   if (result == 0)
-     goto on_error;
-#endif
-
-   /* classic copy method using mmap and write */
-   if (result == -1)
-     {
-#ifndef HAVE_SPLICE
-        struct stat buf;
-
-        if (stat(copy->source, &buf) < 0)
-          goto on_error;
-
-        md = buf.st_mode;
-#endif
-
-        f = eina_file_open(copy->source, 0);
-        if (!f) goto on_error;
-
-        if (!_eio_file_copy_mmap(thread, copy, f, out))
-          {
-             eina_file_close(f);
-             goto on_error;
-          }
+   return !ecore_thread_check(thread);
+}
 
-        _eio_eina_file_copy_xattr(thread, copy, f, out);
+Eina_Bool
+eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy)
+{
+   void *ctx[2] = {thread, copy};
+   Eina_Bool ret = eina_file_copy(copy->source, copy->dest,
+                                  (EINA_FILE_COPY_PERMISSION |
+                                   EINA_FILE_COPY_XATTR),
+                                  _eio_file_copy_progress,
+                                  ctx);
 
-        eina_file_close(f);
-     }
-   else
+   if (!ret)
      {
-#if defined HAVE_XATTR && defined HAVE_SPLICE
-       _eio_file_copy_xattr(thread, copy, in, out);
-#endif
+        eio_file_thread_error(&copy->common, thread);
+        return EINA_FALSE;
      }
 
-   /* change access right to match source */
-#ifdef HAVE_FCHMOD
-   if (fchmod(out, md) != 0)
-     goto on_error;
-#else
-   if (chmod(copy->dest, md) != 0)
-     goto on_error;
-#endif
-
-   close(out);
-#ifdef HAVE_SPLICE
-   close(in);
-#endif
-
    return EINA_TRUE;
-
- on_error:
-   eio_file_thread_error(&copy->common, thread);
-
-#ifdef HAVE_SPLICE
-   if (in >= 0) close(in);
-#endif
-   if (out >= 0) close(out);
-   if (out >= 0)
-     unlink(copy->dest);
-   return EINA_FALSE;
 }
 
 void