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
|
### 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"
|
enable_log="no"
|
||||||
if test "x${efl_func_fnmatch}" = "xyes" && test "x${want_log}" = "xyes" ; then
|
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 linker characteristics
|
||||||
|
|
||||||
### Checks for library functions
|
### Checks for library functions
|
||||||
EFL_CHECK_FUNCS([EIO], [splice setxattr])
|
|
||||||
|
|
||||||
EFL_LIB_END([Eio])
|
EFL_LIB_END([Eio])
|
||||||
#### End of Eio
|
#### End of Eio
|
||||||
|
|
|
@ -12,7 +12,9 @@ AM_CPPFLAGS = \
|
||||||
-I$(top_builddir)/src/lib/ecore \
|
-I$(top_builddir)/src/lib/ecore \
|
||||||
-I$(top_builddir)/src/lib/eio
|
-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_SOURCES = eio_file_ls.c
|
||||||
eio_file_ls_LDADD = \
|
eio_file_ls_LDADD = \
|
||||||
|
@ -23,8 +25,18 @@ $(top_builddir)/src/lib/eet/libeet.la \
|
||||||
$(top_builddir)/src/lib/eina/libeina.la \
|
$(top_builddir)/src/lib/eina/libeina.la \
|
||||||
@EIO_LDFLAGS@
|
@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 = \
|
SRCS = \
|
||||||
eio_file_ls
|
eio_file_ls.c \
|
||||||
|
eio_file_copy.c
|
||||||
|
|
||||||
examples: $(EXTRA_PROGRAMS)
|
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_private.h"
|
||||||
#include "Eio.h"
|
#include "Eio.h"
|
||||||
|
|
||||||
#ifdef HAVE_XATTR
|
|
||||||
# include <sys/xattr.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* Local *
|
* 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
|
#ifndef MAP_HUGETLB
|
||||||
# define MAP_HUGETLB 0
|
# define MAP_HUGETLB 0
|
||||||
#endif
|
#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
|
static void
|
||||||
_eio_file_copy_heavy(void *data, Ecore_Thread *thread)
|
_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);
|
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
|
Eina_Bool
|
||||||
eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy)
|
eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy)
|
||||||
{
|
{
|
||||||
Eina_File *f;
|
void *ctx[2] = {thread, copy};
|
||||||
#ifdef HAVE_SPLICE
|
Eina_Bool ret = eina_file_copy(copy->source, copy->dest,
|
||||||
struct stat buf;
|
(EINA_FILE_COPY_PERMISSION |
|
||||||
int in = -1;
|
EINA_FILE_COPY_XATTR),
|
||||||
#endif
|
_eio_file_copy_progress,
|
||||||
mode_t md;
|
ctx);
|
||||||
int result = -1;
|
|
||||||
int out = -1;
|
|
||||||
|
|
||||||
#ifdef HAVE_SPLICE
|
if (!ret)
|
||||||
in = open(copy->source, O_RDONLY);
|
|
||||||
if (in < 0)
|
|
||||||
{
|
{
|
||||||
eio_file_thread_error(©->common, thread);
|
eio_file_thread_error(©->common, thread);
|
||||||
return EINA_FALSE;
|
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;
|
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
|
void
|
||||||
|
|
Loading…
Reference in New Issue