summaryrefslogtreecommitdiff
path: root/src/lib/eio/eio_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/eio/eio_file.c')
-rw-r--r--src/lib/eio/eio_file.c979
1 files changed, 979 insertions, 0 deletions
diff --git a/src/lib/eio/eio_file.c b/src/lib/eio/eio_file.c
new file mode 100644
index 0000000..ffcd2a7
--- /dev/null
+++ b/src/lib/eio/eio_file.c
@@ -0,0 +1,979 @@
1/* EIO - EFL data type library
2 * Copyright (C) 2010 Enlightenment Developers:
3 * Cedric Bail <cedric.bail@free.fr>
4 * Vincent "caro" Torri <vtorri at univ-evry dot fr>
5 * Stephen "okra" Houston <UnixTitan@gmail.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library;
19 * if not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "eio_private.h"
23#include "Eio.h"
24
25#ifdef HAVE_XATTR
26# include <sys/xattr.h>
27#endif
28
29/*============================================================================*
30 * Local *
31 *============================================================================*/
32
33/**
34 * @cond LOCAL
35 */
36
37static void
38_eio_file_heavy(void *data, Ecore_Thread *thread)
39{
40 Eio_File_Char_Ls *async = data;
41 Eina_Iterator *ls;
42 const char *file;
43 Eina_List *pack = NULL;
44 double start, current;
45
46 ls = eina_file_ls(async->ls.directory);
47 if (!ls)
48 {
49 eio_file_thread_error(&async->ls.common, thread);
50 return ;
51 }
52
53 eio_file_container_set(&async->ls.common, eina_iterator_container_get(ls));
54
55 start = ecore_time_get();
56
57 EINA_ITERATOR_FOREACH(ls, file)
58 {
59 Eina_Bool filter = EINA_TRUE;
60
61 if (async->filter_cb)
62 {
63 filter = async->filter_cb((void*) async->ls.common.data, &async->ls.common, file);
64 }
65
66 if (filter)
67 {
68 Eio_File_Char *send_fc;
69
70 send_fc = eio_char_malloc();
71 if (!send_fc) goto on_error;
72
73 send_fc->filename = file;
74 send_fc->associated = async->ls.common.worker.associated;
75 async->ls.common.worker.associated = NULL;
76
77 pack = eina_list_append(pack, send_fc);
78 }
79 else
80 {
81 on_error:
82 eina_stringshare_del(file);
83
84 if (async->ls.common.worker.associated)
85 {
86 eina_hash_free(async->ls.common.worker.associated);
87 async->ls.common.worker.associated = NULL;
88 }
89 }
90
91 current = ecore_time_get();
92 if (current - start > EIO_PACKED_TIME)
93 {
94 start = current;
95 ecore_thread_feedback(thread, pack);
96 pack = NULL;
97 }
98
99 if (ecore_thread_check(thread))
100 break;
101 }
102
103 if (pack) ecore_thread_feedback(thread, pack);
104
105 eio_file_container_set(&async->ls.common, NULL);
106
107 eina_iterator_free(ls);
108}
109
110static void
111_eio_file_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
112{
113 Eio_File_Char_Ls *async = data;
114 Eina_List *pack = msg_data;
115 Eio_File_Char *info;
116
117 EINA_LIST_FREE(pack, info)
118 {
119 async->ls.common.main.associated = info->associated;
120
121 async->main_cb((void*) async->ls.common.data,
122 &async->ls.common,
123 info->filename);
124
125 if (async->ls.common.main.associated)
126 {
127 eina_hash_free(async->ls.common.main.associated);
128 async->ls.common.main.associated = NULL;
129 }
130
131 eina_stringshare_del(info->filename);
132 eio_char_free(info);
133 }
134}
135
136static void
137_eio_file_eina_ls_heavy(Ecore_Thread *thread, Eio_File_Direct_Ls *async, Eina_Iterator *ls)
138{
139 const Eina_File_Direct_Info *info;
140 Eina_List *pack = NULL;
141 double start, current;
142
143 if (!ls)
144 {
145 eio_file_thread_error(&async->ls.common, thread);
146 return ;
147 }
148
149 eio_file_container_set(&async->ls.common, eina_iterator_container_get(ls));
150
151 start = ecore_time_get();
152
153 EINA_ITERATOR_FOREACH(ls, info)
154 {
155 Eina_Bool filter = EINA_TRUE;
156
157 if (async->filter_cb)
158 {
159 filter = async->filter_cb((void*) async->ls.common.data, &async->ls.common, info);
160 }
161
162 if (filter)
163 {
164 Eio_File_Direct_Info *send_di;
165
166 send_di = eio_direct_info_malloc();
167 if (!send_di) continue;
168
169 memcpy(&send_di->info, info, sizeof (Eina_File_Direct_Info));
170 send_di->associated = async->ls.common.worker.associated;
171 async->ls.common.worker.associated = NULL;
172
173 pack = eina_list_append(pack, send_di);
174 }
175 else if (async->ls.common.worker.associated)
176 {
177 eina_hash_free(async->ls.common.worker.associated);
178 async->ls.common.worker.associated = NULL;
179 }
180
181 current = ecore_time_get();
182 if (current - start > EIO_PACKED_TIME)
183 {
184 start = current;
185 ecore_thread_feedback(thread, pack);
186 pack = NULL;
187 }
188
189 if (ecore_thread_check(thread))
190 break;
191 }
192
193 if (pack) ecore_thread_feedback(thread, pack);
194
195 eio_file_container_set(&async->ls.common, NULL);
196
197 eina_iterator_free(ls);
198}
199
200static void
201_eio_file_direct_heavy(void *data, Ecore_Thread *thread)
202{
203 Eio_File_Direct_Ls *async = data;
204 Eina_Iterator *ls;
205
206 ls = eina_file_direct_ls(async->ls.directory);
207
208 _eio_file_eina_ls_heavy(thread, async, ls);
209}
210
211static void
212_eio_file_stat_heavy(void *data, Ecore_Thread *thread)
213{
214 Eio_File_Direct_Ls *async = data;
215 Eina_Iterator *ls;
216
217 ls = eina_file_stat_ls(async->ls.directory);
218
219 _eio_file_eina_ls_heavy(thread, async, ls);
220}
221
222static void
223_eio_file_direct_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
224{
225 Eio_File_Direct_Ls *async = data;
226 Eina_List *pack = msg_data;
227 Eio_File_Direct_Info *info;
228
229 EINA_LIST_FREE(pack, info)
230 {
231 async->ls.common.main.associated = info->associated;
232
233 async->main_cb((void*) async->ls.common.data,
234 &async->ls.common,
235 &info->info);
236
237 if (async->ls.common.main.associated)
238 {
239 eina_hash_free(async->ls.common.main.associated);
240 async->ls.common.main.associated = NULL;
241 }
242
243 eio_direct_info_free(info);
244 }
245}
246
247static void
248_eio_eina_file_copy_xattr(Ecore_Thread *thread EINA_UNUSED,
249 Eio_File_Progress *op EINA_UNUSED,
250 Eina_File *f, int out)
251{
252 Eina_Iterator *it;
253 Eina_Xattr *attr;
254
255 it = eina_file_xattr_value_get(f);
256 EINA_ITERATOR_FOREACH(it, attr)
257 {
258#ifdef HAVE_XATTR
259 fsetxattr(out, attr->name, attr->value, attr->length, 0);
260#endif
261 }
262 eina_iterator_free(it);
263}
264
265#ifdef HAVE_XATTR
266static void
267_eio_file_copy_xattr(Ecore_Thread *thread EINA_UNUSED,
268 Eio_File_Progress *op EINA_UNUSED,
269 int in, int out)
270{
271 char *tmp;
272 ssize_t length;
273 ssize_t i;
274
275 length = flistxattr(in, NULL, 0);
276
277 if (length <= 0) return ;
278
279 tmp = alloca(length);
280 length = flistxattr(in, tmp, length);
281
282 for (i = 0; i < length; i += strlen(tmp) + 1)
283 {
284 ssize_t attr_length;
285 void *value;
286
287 attr_length = fgetxattr(in, tmp, NULL, 0);
288 if (!attr_length) continue ;
289
290 value = malloc(attr_length);
291 if (!value) continue ;
292 attr_length = fgetxattr(in, tmp, value, attr_length);
293
294 if (attr_length > 0)
295 fsetxattr(out, tmp, value, attr_length, 0);
296
297 free(value);
298 }
299}
300#endif
301
302static Eina_Bool
303_eio_file_write(int fd, void *mem, ssize_t length)
304{
305 ssize_t count;
306
307 if (length == 0) return EINA_TRUE;
308
309 count = write(fd, mem, length);
310 if (count != length) return EINA_FALSE;
311 return EINA_TRUE;
312}
313
314#ifndef MAP_HUGETLB
315# define MAP_HUGETLB 0
316#endif
317
318static Eina_Bool
319_eio_file_copy_mmap(Ecore_Thread *thread, Eio_File_Progress *op, Eina_File *f, int out)
320{
321 char *m = MAP_FAILED;
322 long long i;
323 long long size;
324
325 size = eina_file_size_get(f);
326
327 for (i = 0; i < size; i += EIO_PACKET_SIZE * EIO_PACKET_COUNT)
328 {
329 int j;
330 int k;
331 int c;
332
333 m = eina_file_map_new(f, EINA_FILE_SEQUENTIAL,
334 i, EIO_PACKET_SIZE * EIO_PACKET_COUNT);
335 if (!m)
336 goto on_error;
337
338 c = size - i;
339 if (c - EIO_PACKET_SIZE * EIO_PACKET_COUNT > 0)
340 c = EIO_PACKET_SIZE * EIO_PACKET_COUNT;
341 else
342 c = size - i;
343
344 for (j = EIO_PACKET_SIZE, k = 0; j < c; k = j, j += EIO_PACKET_SIZE)
345 {
346 if (!_eio_file_write(out, m + k, EIO_PACKET_SIZE))
347 goto on_error;
348
349 eio_progress_send(thread, op, i + j, size);
350 }
351
352 if (!_eio_file_write(out, m + k, c - k))
353 goto on_error;
354
355 if (eina_file_map_faulted(f, m))
356 goto on_error;
357
358 eio_progress_send(thread, op, i + c, size);
359
360 eina_file_map_free(f, m);
361 m = NULL;
362
363 if (ecore_thread_check(thread))
364 goto on_error;
365 }
366
367 return EINA_TRUE;
368
369 on_error:
370 if (m != NULL) eina_file_map_free(f, m);
371 return EINA_FALSE;
372}
373
374#ifdef HAVE_SPLICE
375static int
376_eio_file_copy_splice(Ecore_Thread *thread, Eio_File_Progress *op, int in, int out, long long size)
377{
378 int result = 0;
379 long long count;
380 long long i;
381 int pipefd[2];
382
383 if (pipe(pipefd) < 0)
384 return -1;
385
386 for (i = 0; i < size; i += count)
387 {
388 count = splice(in, 0, pipefd[1], NULL, EIO_PACKET_SIZE * EIO_PACKET_COUNT, SPLICE_F_MORE | SPLICE_F_MOVE);
389 if (count < 0) goto on_error;
390
391 count = splice(pipefd[0], NULL, out, 0, count, SPLICE_F_MORE | SPLICE_F_MOVE);
392 if (count < 0) goto on_error;
393
394 eio_progress_send(thread, op, i, size);
395
396 if (ecore_thread_check(thread))
397 goto on_error;
398 }
399
400 result = 1;
401
402 on_error:
403 if (result != 1 && (errno == EBADF || errno == EINVAL)) result = -1;
404 close(pipefd[0]);
405 close(pipefd[1]);
406
407 return result;
408}
409#endif
410
411static void
412_eio_file_copy_heavy(void *data, Ecore_Thread *thread)
413{
414 Eio_File_Progress *copy = data;
415
416 eio_file_copy_do(thread, copy);
417}
418
419static void
420_eio_file_copy_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
421{
422 Eio_File_Progress *copy = data;
423
424 eio_progress_cb(msg_data, copy);
425}
426
427static void
428_eio_file_copy_free(Eio_File_Progress *copy)
429{
430 eina_stringshare_del(copy->source);
431 eina_stringshare_del(copy->dest);
432 eio_file_free(&copy->common);
433}
434
435static void
436_eio_file_copy_end(void *data, Ecore_Thread *thread EINA_UNUSED)
437{
438 Eio_File_Progress *copy = data;
439
440 copy->common.done_cb((void*) copy->common.data, &copy->common);
441
442 _eio_file_copy_free(copy);
443}
444
445static void
446_eio_file_copy_error(void *data, Ecore_Thread *thread EINA_UNUSED)
447{
448 Eio_File_Progress *copy = data;
449
450 eio_file_error(&copy->common);
451
452 _eio_file_copy_free(copy);
453}
454
455static void
456_eio_file_move_free(Eio_File_Move *move)
457{
458 eina_stringshare_del(move->progress.source);
459 eina_stringshare_del(move->progress.dest);
460 eio_file_free(&move->progress.common);
461}
462
463static void
464_eio_file_move_copy_progress(void *data, Eio_File *handler EINA_UNUSED, const Eio_Progress *info)
465{
466 Eio_File_Move *move = data;
467
468 move->progress.progress_cb((void*) move->progress.common.data, &move->progress.common, info);
469}
470
471static void
472_eio_file_move_unlink_done(void *data, Eio_File *handler EINA_UNUSED)
473{
474 Eio_File_Move *move = data;
475
476 move->progress.common.done_cb((void*) move->progress.common.data, &move->progress.common);
477
478 _eio_file_move_free(move);
479}
480
481static void
482_eio_file_move_unlink_error(void *data, Eio_File *handler EINA_UNUSED, int error)
483{
484 Eio_File_Move *move = data;
485
486 move->copy = NULL;
487
488 move->progress.common.error = error;
489 eio_file_error(&move->progress.common);
490
491 _eio_file_move_free(move);
492}
493
494static void
495_eio_file_move_copy_done(void *data, Eio_File *handler EINA_UNUSED)
496{
497 Eio_File_Move *move = data;
498 Eio_File *rm;
499
500 rm = eio_file_unlink(move->progress.source,
501 _eio_file_move_unlink_done,
502 _eio_file_move_unlink_error,
503 move);
504 if (rm) move->copy = rm;
505}
506
507static void
508_eio_file_move_copy_error(void *data, Eio_File *handler EINA_UNUSED, int error)
509{
510 Eio_File_Move *move = data;
511
512 move->progress.common.error = error;
513 eio_file_error(&move->progress.common);
514
515 _eio_file_move_free(move);
516}
517
518static void
519_eio_file_move_heavy(void *data, Ecore_Thread *thread)
520{
521 Eio_File_Move *move = data;
522
523 if (rename(move->progress.source, move->progress.dest) < 0)
524 eio_file_thread_error(&move->progress.common, thread);
525 else
526 eio_progress_send(thread, &move->progress, 1, 1);
527}
528
529static void
530_eio_file_move_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
531{
532 Eio_File_Move *move = data;
533
534 eio_progress_cb(msg_data, &move->progress);
535}
536
537static void
538_eio_file_move_end(void *data, Ecore_Thread *thread EINA_UNUSED)
539{
540 Eio_File_Move *move = data;
541
542 move->progress.common.done_cb((void*) move->progress.common.data, &move->progress.common);
543
544 _eio_file_move_free(move);
545}
546
547static void
548_eio_file_move_error(void *data, Ecore_Thread *thread EINA_UNUSED)
549{
550 Eio_File_Move *move = data;
551
552 if (move->copy)
553 {
554 eio_file_cancel(move->copy);
555 return ;
556 }
557
558 if (move->progress.common.error == EXDEV)
559 {
560 Eio_File *eio_cp;
561
562 eio_cp = eio_file_copy(move->progress.source, move->progress.dest,
563 move->progress.progress_cb ? _eio_file_move_copy_progress : NULL,
564 _eio_file_move_copy_done,
565 _eio_file_move_copy_error,
566 move);
567
568 if (eio_cp)
569 {
570 move->copy = eio_cp;
571
572 move->progress.common.thread = ((Eio_File_Progress*)move->copy)->common.thread;
573 return ;
574 }
575 }
576
577 eio_file_error(&move->progress.common);
578
579 _eio_file_move_free(move);
580}
581
582/**
583 * @endcond
584 */
585
586
587/*============================================================================*
588 * Global *
589 *============================================================================*/
590
591/**
592 * @cond LOCAL
593 */
594
595void
596eio_progress_cb(Eio_Progress *progress, Eio_File_Progress *op)
597{
598 op->progress_cb((void *) op->common.data, &op->common, progress);
599
600 eio_progress_free(progress);
601}
602
603Eina_Bool
604eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy)
605{
606 Eina_File *f;
607#ifdef HAVE_SPLICE
608 struct stat buf;
609 int in = -1;
610#endif
611 mode_t md;
612 int result = -1;
613 int out = -1;
614
615#ifdef HAVE_SPLICE
616 in = open(copy->source, O_RDONLY);
617 if (in < 0)
618 {
619 eio_file_thread_error(&copy->common, thread);
620 return EINA_FALSE;
621 }
622
623 /*
624 As we need file size for progression information and both copy method
625 call fstat (better than stat as it avoid race condition).
626 */
627 if (fstat(in, &buf) < 0)
628 goto on_error;
629
630 md = buf.st_mode;
631#endif
632
633 /* open write */
634 out = open(copy->dest, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
635 if (out < 0)
636 goto on_error;
637
638#ifdef HAVE_SPLICE
639 /* fast file copy code using Linux splice API */
640 result = _eio_file_copy_splice(thread, copy, in, out, buf.st_size);
641 if (result == 0)
642 goto on_error;
643#endif
644
645 /* classic copy method using mmap and write */
646 if (result == -1)
647 {
648#ifndef HAVE_SPLICE
649 struct stat buf;
650
651 if (stat(copy->source, &buf) < 0)
652 goto on_error;
653
654 md = buf.st_mode;
655#endif
656
657 f = eina_file_open(copy->source, 0);
658 if (!f) goto on_error;
659
660 if (!_eio_file_copy_mmap(thread, copy, f, out))
661 {
662 eina_file_close(f);
663 goto on_error;
664 }
665
666 _eio_eina_file_copy_xattr(thread, copy, f, out);
667
668 eina_file_close(f);
669 }
670 else
671 {
672#if defined HAVE_XATTR && defined HAVE_SPLICE
673 _eio_file_copy_xattr(thread, copy, in, out);
674#endif
675 }
676
677 /* change access right to match source */
678#ifdef HAVE_CHMOD
679 if (fchmod(out, md) != 0)
680 goto on_error;
681#else
682 if (chmod(copy->dest, md) != 0)
683 goto on_error;
684#endif
685
686 close(out);
687#ifdef HAVE_SPLICE
688 close(in);
689#endif
690
691 return EINA_TRUE;
692
693 on_error:
694 eio_file_thread_error(&copy->common, thread);
695
696#ifdef HAVE_SPLICE
697 if (in >= 0) close(in);
698#endif
699 if (out >= 0) close(out);
700 if (out >= 0)
701 unlink(copy->dest);
702 return EINA_FALSE;
703}
704
705void
706eio_async_free(Eio_File_Ls *async)
707{
708 eina_stringshare_del(async->directory);
709 eio_file_free(&async->common);
710}
711
712void
713eio_async_end(void *data, Ecore_Thread *thread EINA_UNUSED)
714{
715 Eio_File_Ls *async = data;
716
717 async->common.done_cb((void*) async->common.data, &async->common);
718
719 eio_async_free(async);
720}
721
722void
723eio_async_error(void *data, Ecore_Thread *thread EINA_UNUSED)
724{
725 Eio_File_Ls *async = data;
726
727 eio_file_error(&async->common);
728
729 eio_async_free(async);
730}
731
732/**
733 * @endcond
734 */
735
736
737/*============================================================================*
738 * API *
739 *============================================================================*/
740
741EAPI Eio_File *
742eio_file_ls(const char *dir,
743 Eio_Filter_Cb filter_cb,
744 Eio_Main_Cb main_cb,
745 Eio_Done_Cb done_cb,
746 Eio_Error_Cb error_cb,
747 const void *data)
748{
749 Eio_File_Char_Ls *async;
750
751 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
752 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
753 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
754 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
755
756 async = malloc(sizeof (Eio_File_Char_Ls));
757 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
758
759 async->filter_cb = filter_cb;
760 async->main_cb = main_cb;
761 async->ls.directory = eina_stringshare_add(dir);
762
763 if (!eio_long_file_set(&async->ls.common,
764 done_cb,
765 error_cb,
766 data,
767 _eio_file_heavy,
768 _eio_file_notify,
769 eio_async_end,
770 eio_async_error))
771 return NULL;
772
773 return &async->ls.common;
774}
775
776EAPI Eio_File *
777eio_file_direct_ls(const char *dir,
778 Eio_Filter_Direct_Cb filter_cb,
779 Eio_Main_Direct_Cb main_cb,
780 Eio_Done_Cb done_cb,
781 Eio_Error_Cb error_cb,
782 const void *data)
783{
784 Eio_File_Direct_Ls *async;
785
786 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
787 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
788 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
789 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
790
791 async = malloc(sizeof(Eio_File_Direct_Ls));
792 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
793
794 async->filter_cb = filter_cb;
795 async->main_cb = main_cb;
796 async->ls.directory = eina_stringshare_add(dir);
797
798 if (!eio_long_file_set(&async->ls.common,
799 done_cb,
800 error_cb,
801 data,
802 _eio_file_direct_heavy,
803 _eio_file_direct_notify,
804 eio_async_end,
805 eio_async_error))
806 return NULL;
807
808 return &async->ls.common;
809}
810
811EAPI Eio_File *
812eio_file_stat_ls(const char *dir,
813 Eio_Filter_Direct_Cb filter_cb,
814 Eio_Main_Direct_Cb main_cb,
815 Eio_Done_Cb done_cb,
816 Eio_Error_Cb error_cb,
817 const void *data)
818{
819 Eio_File_Direct_Ls *async;
820
821 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
822 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
823 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
824 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
825
826 async = malloc(sizeof(Eio_File_Direct_Ls));
827 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
828
829 async->filter_cb = filter_cb;
830 async->main_cb = main_cb;
831 async->ls.directory = eina_stringshare_add(dir);
832
833 if (!eio_long_file_set(&async->ls.common,
834 done_cb,
835 error_cb,
836 data,
837 _eio_file_stat_heavy,
838 _eio_file_direct_notify,
839 eio_async_end,
840 eio_async_error))
841 return NULL;
842
843 return &async->ls.common;
844}
845
846EAPI Eina_Bool
847eio_file_cancel(Eio_File *ls)
848{
849 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, EINA_FALSE);
850 return ecore_thread_cancel(ls->thread);
851}
852
853EAPI Eina_Bool
854eio_file_check(Eio_File *ls)
855{
856 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, EINA_TRUE);
857 return ecore_thread_check(ls->thread);
858}
859
860EAPI void *
861eio_file_container_get(Eio_File *ls)
862{
863 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, EINA_FALSE);
864 return ls->container;
865}
866
867EAPI Eina_Bool
868eio_file_associate_add(Eio_File *ls,
869 const char *key,
870 const void *data, Eina_Free_Cb free_cb)
871{
872 /* FIXME: Check if we are in the right worker thred */
873 if (!ls->worker.associated)
874 ls->worker.associated = eina_hash_string_small_new(eio_associate_free);
875
876 return eina_hash_add(ls->worker.associated,
877 key,
878 eio_associate_malloc(data, free_cb));
879}
880
881EAPI Eina_Bool
882eio_file_associate_direct_add(Eio_File *ls,
883 const char *key,
884 const void *data, Eina_Free_Cb free_cb)
885{
886 /* FIXME: Check if we are in the right worker thred */
887 if (!ls->worker.associated)
888 ls->worker.associated = eina_hash_string_small_new(eio_associate_free);
889
890 return eina_hash_direct_add(ls->worker.associated,
891 key,
892 eio_associate_malloc(data, free_cb));
893}
894
895EAPI void *
896eio_file_associate_find(Eio_File *ls, const char *key)
897{
898 Eio_File_Associate *search;
899
900 if (!ls->main.associated)
901 return NULL;
902
903 search = eina_hash_find(ls->main.associated, key);
904 if (!search) return NULL;
905 return search->data;
906}
907
908EAPI Eio_File *
909eio_file_copy(const char *source,
910 const char *dest,
911 Eio_Progress_Cb progress_cb,
912 Eio_Done_Cb done_cb,
913 Eio_Error_Cb error_cb,
914 const void *data)
915{
916 Eio_File_Progress *copy;
917
918 EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL);
919 EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL);
920 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
921 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
922
923 copy = malloc(sizeof(Eio_File_Progress));
924 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, NULL);
925
926 copy->op = EIO_FILE_COPY;
927 copy->progress_cb = progress_cb;
928 copy->source = eina_stringshare_add(source);
929 copy->dest = eina_stringshare_add(dest);
930
931 if (!eio_long_file_set(&copy->common,
932 done_cb,
933 error_cb,
934 data,
935 _eio_file_copy_heavy,
936 _eio_file_copy_notify,
937 _eio_file_copy_end,
938 _eio_file_copy_error))
939 return NULL;
940
941 return &copy->common;
942}
943
944EAPI Eio_File *
945eio_file_move(const char *source,
946 const char *dest,
947 Eio_Progress_Cb progress_cb,
948 Eio_Done_Cb done_cb,
949 Eio_Error_Cb error_cb,
950 const void *data)
951{
952 Eio_File_Move *move;
953
954 EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL);
955 EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL);
956 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
957 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
958
959 move = malloc(sizeof(Eio_File_Move));
960 EINA_SAFETY_ON_NULL_RETURN_VAL(move, NULL);
961
962 move->progress.op = EIO_FILE_MOVE;
963 move->progress.progress_cb = progress_cb;
964 move->progress.source = eina_stringshare_add(source);
965 move->progress.dest = eina_stringshare_add(dest);
966 move->copy = NULL;
967
968 if (!eio_long_file_set(&move->progress.common,
969 done_cb,
970 error_cb,
971 data,
972 _eio_file_move_heavy,
973 _eio_file_move_notify,
974 _eio_file_move_end,
975 _eio_file_move_error))
976 return NULL;
977
978 return &move->progress.common;
979}