forked from enlightenment/efl
parent
43eb232d38
commit
014cd8065d
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -22,10 +22,6 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eio_file_copy_progress(void *data, unsigned long long done, unsigned long long total)
|
||||
{
|
||||
void **ctx = data;
|
||||
Ecore_Thread *thread = ctx[0];
|
||||
Eio_File_Progress *copy = ctx[1];
|
||||
|
||||
eio_progress_send(thread, copy, done, total);
|
||||
|
||||
return !ecore_thread_check(thread);
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy)
|
||||
{
|
||||
Eina_File *f;
|
||||
#ifdef HAVE_SPLICE
|
||||
struct stat buf;
|
||||
int in = -1;
|
||||
#endif
|
||||
mode_t md;
|
||||
int result = -1;
|
||||
int out = -1;
|
||||
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);
|
||||
|
||||
#ifdef HAVE_SPLICE
|
||||
in = open(copy->source, O_RDONLY);
|
||||
if (in < 0)
|
||||
if (!ret)
|
||||
{
|
||||
eio_file_thread_error(©->common, thread);
|
||||
return EINA_FALSE;
|
||||
eio_file_thread_error(©->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;
|
||||
|
||||
md = buf.st_mode;
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
_eio_eina_file_copy_xattr(thread, copy, f, out);
|
||||
|
||||
eina_file_close(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined HAVE_XATTR && defined HAVE_SPLICE
|
||||
_eio_file_copy_xattr(thread, copy, in, out);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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(©->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
|
||||
|
|
Loading…
Reference in New Issue