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 /*============================================================================*
26 * Local *
27 *============================================================================*/
28
29 /**
30 * @cond LOCAL
31 */
32
33 static void
_eio_file_heavy(void * data,Ecore_Thread * thread)34 _eio_file_heavy(void *data, Ecore_Thread *thread)
35 {
36 Eio_File_Char_Ls *async = data;
37 Eina_Iterator *ls;
38 const char *file;
39 Eina_List *pack = NULL;
40 double start;
41
42 ls = eina_file_ls(async->ls.directory);
43 if (!ls)
44 {
45 eio_file_thread_error(&async->ls.common, thread);
46 return;
47 }
48
49 eio_file_container_set(&async->ls.common, eina_iterator_container_get(ls));
50
51 start = ecore_time_get();
52
53 EINA_ITERATOR_FOREACH(ls, file)
54 {
55 Eina_Bool filter = EINA_TRUE;
56
57 if (async->filter_cb)
58 {
59 filter = async->filter_cb((void*) async->ls.common.data, &async->ls.common, file);
60 }
61
62 if (filter)
63 {
64 Eio_File_Char *send_fc;
65
66 send_fc = eio_char_malloc();
67 if (!send_fc) goto on_error;
68
69 send_fc->filename = file;
70 send_fc->associated = async->ls.common.worker.associated;
71 async->ls.common.worker.associated = NULL;
72
73 pack = eina_list_append(pack, send_fc);
74 }
75 else
76 {
77 on_error:
78 eina_stringshare_del(file);
79
80 if (async->ls.common.worker.associated)
81 {
82 eina_hash_free(async->ls.common.worker.associated);
83 async->ls.common.worker.associated = NULL;
84 }
85 }
86
87 pack = eio_pack_send(thread, pack, &start);
88
89 if (ecore_thread_check(thread))
90 break;
91 }
92
93 if (pack) ecore_thread_feedback(thread, pack);
94
95 async->ls.ls = ls;
96 }
97
98 void
_eio_string_notify(void * data,Ecore_Thread * thread EINA_UNUSED,void * msg_data)99 _eio_string_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
100 {
101 Eio_File_Char_Ls *async = data;
102 Eina_List *pack = msg_data;
103 Eio_File_Char *info;
104
105 async->ls.common.length += eina_list_count(pack);
106
107 // Check if it is an internal use
108 if (async->ls.gather)
109 {
110 Eina_Array *gather;
111
112 gather = eina_array_new(eina_list_count(pack));
113 EINA_LIST_FREE(pack, info)
114 {
115 if (!gather)
116 eina_stringshare_del(info->filename);
117 else
118 eina_array_push(gather, info->filename);
119 eio_char_free(info);
120 }
121
122 // transfer ownership to caller
123 async->main_internal_cb((void*) async->ls.common.data,
124 &async->ls.common,
125 gather);
126
127 return ;
128 }
129
130 EINA_LIST_FREE(pack, info)
131 {
132 async->ls.common.main.associated = info->associated;
133
134 async->main_cb((void*) async->ls.common.data,
135 &async->ls.common,
136 info->filename);
137
138 if (async->ls.common.main.associated)
139 {
140 eina_hash_free(async->ls.common.main.associated);
141 async->ls.common.main.associated = NULL;
142 }
143
144 eina_stringshare_del(info->filename);
145 eio_char_free(info);
146 }
147 }
148
149 static void
_eio_file_eina_ls_heavy(Ecore_Thread * thread,Eio_File_Direct_Ls * async,Eina_Iterator * ls)150 _eio_file_eina_ls_heavy(Ecore_Thread *thread, Eio_File_Direct_Ls *async, Eina_Iterator *ls)
151 {
152 const Eina_File_Direct_Info *info;
153 Eina_List *pack = NULL;
154 double start;
155
156 if (!ls)
157 {
158 eio_file_thread_error(&async->ls.common, thread);
159 return;
160 }
161
162 eio_file_container_set(&async->ls.common, eina_iterator_container_get(ls));
163
164 start = ecore_time_get();
165
166 EINA_ITERATOR_FOREACH(ls, info)
167 {
168 Eina_Bool filter = EINA_TRUE;
169
170 if (async->filter_cb)
171 {
172 filter = async->filter_cb((void*) async->ls.common.data, &async->ls.common, info);
173 }
174
175 if (filter)
176 {
177 Eio_File_Direct_Info *send_di;
178
179 send_di = eio_direct_info_malloc();
180 if (!send_di) continue;
181
182 memcpy(&send_di->info, info, sizeof (Eina_File_Direct_Info));
183 send_di->associated = async->ls.common.worker.associated;
184 async->ls.common.worker.associated = NULL;
185
186 pack = eina_list_append(pack, send_di);
187 }
188 else if (async->ls.common.worker.associated)
189 {
190 eina_hash_free(async->ls.common.worker.associated);
191 async->ls.common.worker.associated = NULL;
192 }
193
194 pack = eio_pack_send(thread, pack, &start);
195
196 if (ecore_thread_check(thread))
197 break;
198 }
199
200 if (pack) ecore_thread_feedback(thread, pack);
201
202 async->ls.ls = ls;
203 }
204
205 static void
_eio_file_direct_heavy(void * data,Ecore_Thread * thread)206 _eio_file_direct_heavy(void *data, Ecore_Thread *thread)
207 {
208 Eio_File_Direct_Ls *async = data;
209 Eina_Iterator *ls;
210
211 ls = eina_file_direct_ls(async->ls.directory);
212
213 _eio_file_eina_ls_heavy(thread, async, ls);
214 }
215
216 static void
_eio_file_stat_heavy(void * data,Ecore_Thread * thread)217 _eio_file_stat_heavy(void *data, Ecore_Thread *thread)
218 {
219 Eio_File_Direct_Ls *async = data;
220 Eina_Iterator *ls;
221
222 ls = eina_file_stat_ls(async->ls.directory);
223
224 _eio_file_eina_ls_heavy(thread, async, ls);
225 }
226
227 void
_eio_direct_notify(void * data,Ecore_Thread * thread EINA_UNUSED,void * msg_data)228 _eio_direct_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
229 {
230 Eio_File_Direct_Ls *async = data;
231 Eina_List *pack = msg_data;
232 Eio_File_Direct_Info *info;
233
234 async->ls.common.length += eina_list_count(pack);
235
236 // Check if it is an internal use
237 if (async->ls.gather)
238 {
239 Eina_Array *gather;
240
241 gather = eina_array_new(eina_list_count(pack));
242 EINA_LIST_FREE(pack, info)
243 eina_array_push(gather, &info->info);
244
245 // transfer ownership to caller
246 async->main_internal_cb((void*) async->ls.common.data,
247 &async->ls.common,
248 gather);
249
250 return ;
251 }
252
253 EINA_LIST_FREE(pack, info)
254 {
255 async->ls.common.main.associated = info->associated;
256
257 async->main_cb((void*) async->ls.common.data,
258 &async->ls.common,
259 &info->info);
260
261 if (async->ls.common.main.associated)
262 {
263 eina_hash_free(async->ls.common.main.associated);
264 async->ls.common.main.associated = NULL;
265 }
266
267 eio_direct_info_free(info);
268 }
269 }
270
271 #ifndef MAP_HUGETLB
272 # define MAP_HUGETLB 0
273 #endif
274
275 static void
_eio_file_copy_heavy(void * data,Ecore_Thread * thread)276 _eio_file_copy_heavy(void *data, Ecore_Thread *thread)
277 {
278 Eio_File_Progress *copy = data;
279
280 eio_file_copy_do(thread, copy);
281 }
282
283 static void
_eio_file_copy_notify(void * data,Ecore_Thread * thread EINA_UNUSED,void * msg_data)284 _eio_file_copy_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
285 {
286 Eio_File_Progress *copy = data;
287
288 eio_progress_cb(msg_data, copy);
289 }
290
291 static void
_eio_file_copy_free(Eio_File_Progress * copy)292 _eio_file_copy_free(Eio_File_Progress *copy)
293 {
294 eina_stringshare_del(copy->source);
295 eina_stringshare_del(copy->dest);
296 eio_file_free(©->common);
297 }
298
299 static void
_eio_file_copy_end(void * data,Ecore_Thread * thread EINA_UNUSED)300 _eio_file_copy_end(void *data, Ecore_Thread *thread EINA_UNUSED)
301 {
302 Eio_File_Progress *copy = data;
303
304 copy->common.done_cb((void*) copy->common.data, ©->common);
305
306 _eio_file_copy_free(copy);
307 }
308
309 static void
_eio_file_copy_error(void * data,Ecore_Thread * thread EINA_UNUSED)310 _eio_file_copy_error(void *data, Ecore_Thread *thread EINA_UNUSED)
311 {
312 Eio_File_Progress *copy = data;
313
314 eio_file_error(©->common);
315
316 _eio_file_copy_free(copy);
317 }
318
319 static void
_eio_file_move_free(Eio_File_Move * move)320 _eio_file_move_free(Eio_File_Move *move)
321 {
322 eina_stringshare_del(move->progress.source);
323 eina_stringshare_del(move->progress.dest);
324 eio_file_free(&move->progress.common);
325 }
326
327 static void
_eio_file_move_copy_progress(void * data,Eio_File * handler EINA_UNUSED,const Eio_Progress * info)328 _eio_file_move_copy_progress(void *data, Eio_File *handler EINA_UNUSED, const Eio_Progress *info)
329 {
330 Eio_File_Move *move = data;
331
332 move->progress.progress_cb((void*) move->progress.common.data, &move->progress.common, info);
333 }
334
335 static void
_eio_file_move_unlink_done(void * data,Eio_File * handler EINA_UNUSED)336 _eio_file_move_unlink_done(void *data, Eio_File *handler EINA_UNUSED)
337 {
338 Eio_File_Move *move = data;
339
340 move->progress.common.done_cb((void*) move->progress.common.data, &move->progress.common);
341
342 _eio_file_move_free(move);
343 }
344
345 static void
_eio_file_move_unlink_error(void * data,Eio_File * handler EINA_UNUSED,int error)346 _eio_file_move_unlink_error(void *data, Eio_File *handler EINA_UNUSED, int error)
347 {
348 Eio_File_Move *move = data;
349
350 move->copy = NULL;
351
352 move->progress.common.error = error;
353 eio_file_error(&move->progress.common);
354
355 _eio_file_move_free(move);
356 }
357
358 static void
_eio_file_move_copy_done(void * data,Eio_File * handler EINA_UNUSED)359 _eio_file_move_copy_done(void *data, Eio_File *handler EINA_UNUSED)
360 {
361 Eio_File_Move *move = data;
362 Eio_File *rm;
363
364 rm = eio_file_unlink(move->progress.source,
365 _eio_file_move_unlink_done,
366 _eio_file_move_unlink_error,
367 move);
368 if (rm) move->copy = rm;
369 }
370
371 static void
_eio_file_move_copy_error(void * data,Eio_File * handler EINA_UNUSED,int error)372 _eio_file_move_copy_error(void *data, Eio_File *handler EINA_UNUSED, int error)
373 {
374 Eio_File_Move *move = data;
375
376 move->progress.common.error = error;
377 eio_file_error(&move->progress.common);
378
379 _eio_file_move_free(move);
380 }
381
382 static void
_eio_file_move_heavy(void * data,Ecore_Thread * thread)383 _eio_file_move_heavy(void *data, Ecore_Thread *thread)
384 {
385 Eio_File_Move *move = data;
386
387 if (rename(move->progress.source, move->progress.dest) < 0)
388 eio_file_thread_error(&move->progress.common, thread);
389 else
390 eio_progress_send(thread, &move->progress, 1, 1);
391 }
392
393 static void
_eio_file_move_notify(void * data,Ecore_Thread * thread EINA_UNUSED,void * msg_data)394 _eio_file_move_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
395 {
396 Eio_File_Move *move = data;
397
398 eio_progress_cb(msg_data, &move->progress);
399 }
400
401 static void
_eio_file_move_end(void * data,Ecore_Thread * thread EINA_UNUSED)402 _eio_file_move_end(void *data, Ecore_Thread *thread EINA_UNUSED)
403 {
404 Eio_File_Move *move = data;
405
406 move->progress.common.done_cb((void*) move->progress.common.data, &move->progress.common);
407
408 _eio_file_move_free(move);
409 }
410
411 static void
_eio_file_move_error(void * data,Ecore_Thread * thread EINA_UNUSED)412 _eio_file_move_error(void *data, Ecore_Thread *thread EINA_UNUSED)
413 {
414 Eio_File_Move *move = data;
415
416 if (move->copy)
417 {
418 eio_file_cancel(move->copy);
419 return;
420 }
421
422 if (move->progress.common.error == EXDEV)
423 {
424 Eio_File *eio_cp;
425
426 eio_cp = eio_file_copy(move->progress.source, move->progress.dest,
427 move->progress.progress_cb ? _eio_file_move_copy_progress : NULL,
428 _eio_file_move_copy_done,
429 _eio_file_move_copy_error,
430 move);
431
432 if (eio_cp)
433 {
434 move->copy = eio_cp;
435 move->progress.common.thread = ((Eio_File_Progress*)move->copy)->common.thread;
436 return;
437 }
438 }
439
440 eio_file_error(&move->progress.common);
441
442 _eio_file_move_free(move);
443 }
444
445 /**
446 * @endcond
447 */
448
449
450 /*============================================================================*
451 * Global *
452 *============================================================================*/
453
454 /**
455 * @cond LOCAL
456 */
457
458 void
eio_progress_cb(Eio_Progress * progress,Eio_File_Progress * op)459 eio_progress_cb(Eio_Progress *progress, Eio_File_Progress *op)
460 {
461 op->progress_cb((void *) op->common.data, &op->common, progress);
462
463 eio_progress_free(progress);
464 }
465
466 static Eina_Bool
_eio_file_copy_progress(void * data,unsigned long long done,unsigned long long total)467 _eio_file_copy_progress(void *data, unsigned long long done, unsigned long long total)
468 {
469 void **ctx = data;
470 Ecore_Thread *thread = ctx[0];
471 Eio_File_Progress *copy = ctx[1];
472
473 eio_progress_send(thread, copy, done, total);
474
475 return !ecore_thread_check(thread);
476 }
477
478 Eina_Bool
eio_file_copy_do(Ecore_Thread * thread,Eio_File_Progress * copy)479 eio_file_copy_do(Ecore_Thread *thread, Eio_File_Progress *copy)
480 {
481 void *ctx[2] = {thread, copy};
482 Eina_Bool ret = eina_file_copy(copy->source, copy->dest,
483 (EINA_FILE_COPY_PERMISSION |
484 EINA_FILE_COPY_XATTR),
485 _eio_file_copy_progress,
486 ctx);
487
488 if (!ret)
489 {
490 eio_file_thread_error(©->common, thread);
491 return EINA_FALSE;
492 }
493
494 return EINA_TRUE;
495 }
496
497 void
eio_async_free(Eio_File_Ls * async)498 eio_async_free(Eio_File_Ls *async)
499 {
500 eina_stringshare_del(async->directory);
501 eio_file_free(&async->common);
502 }
503
504 void
eio_async_end(void * data,Ecore_Thread * thread EINA_UNUSED)505 eio_async_end(void *data, Ecore_Thread *thread EINA_UNUSED)
506 {
507 Eio_File_Ls *async = data;
508
509 async->common.done_cb((void*) async->common.data, &async->common);
510 eio_file_container_set(&async->common, NULL);
511 eina_iterator_free(async->ls);
512 eio_async_free(async);
513 }
514
515 void
eio_async_error(void * data,Ecore_Thread * thread EINA_UNUSED)516 eio_async_error(void *data, Ecore_Thread *thread EINA_UNUSED)
517 {
518 Eio_File_Ls *async = data;
519
520 eio_file_error(&async->common);
521
522 eio_async_free(async);
523 }
524
525 /**
526 * @endcond
527 */
528
529
530 /*============================================================================*
531 * API *
532 *============================================================================*/
533 static Eio_File *
_eio_file_internal_ls(const char * dir,Eio_Filter_Cb filter_cb,Eio_Main_Cb main_cb,Eio_Array_Cb main_internal_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)534 _eio_file_internal_ls(const char *dir,
535 Eio_Filter_Cb filter_cb,
536 Eio_Main_Cb main_cb,
537 Eio_Array_Cb main_internal_cb,
538 Eio_Done_Cb done_cb,
539 Eio_Error_Cb error_cb,
540 const void *data)
541 {
542 Eio_File_Char_Ls *async;
543
544 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
545 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
546 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
547
548 async = eio_common_alloc(sizeof(Eio_File_Char_Ls));
549 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
550
551 async->ls.directory = eina_stringshare_add(dir);
552 async->filter_cb = filter_cb;
553 if (main_internal_cb)
554 {
555 async->main_internal_cb = main_internal_cb;
556 async->ls.gather = EINA_TRUE;
557 }
558 else
559 {
560 async->main_cb = main_cb;
561 }
562
563 if (!eio_long_file_set(&async->ls.common,
564 done_cb,
565 error_cb,
566 data,
567 _eio_file_heavy,
568 _eio_string_notify,
569 eio_async_end,
570 eio_async_error))
571 return NULL;
572
573 return &async->ls.common;
574 }
575
576 EAPI Eio_File *
eio_file_ls(const char * dir,Eio_Filter_Cb filter_cb,Eio_Main_Cb main_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)577 eio_file_ls(const char *dir,
578 Eio_Filter_Cb filter_cb,
579 Eio_Main_Cb main_cb,
580 Eio_Done_Cb done_cb,
581 Eio_Error_Cb error_cb,
582 const void *data)
583 {
584 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
585
586 return _eio_file_internal_ls(dir, filter_cb, main_cb, NULL, done_cb, error_cb, data);
587 }
588
589 Eio_File *
_eio_file_ls(const char * dir,Eio_Array_Cb main_internal_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)590 _eio_file_ls(const char *dir,
591 Eio_Array_Cb main_internal_cb,
592 Eio_Done_Cb done_cb,
593 Eio_Error_Cb error_cb,
594 const void *data)
595 {
596 EINA_SAFETY_ON_NULL_RETURN_VAL(main_internal_cb, NULL);
597
598 return _eio_file_internal_ls(dir, NULL, NULL, main_internal_cb, done_cb, error_cb, data);
599 }
600
601 static Eio_File *
_eio_file_direct_internal_ls(const char * dir,Eio_Filter_Direct_Cb filter_cb,Eio_Main_Direct_Cb main_cb,Eio_Array_Cb main_internal_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)602 _eio_file_direct_internal_ls(const char *dir,
603 Eio_Filter_Direct_Cb filter_cb,
604 Eio_Main_Direct_Cb main_cb,
605 Eio_Array_Cb main_internal_cb,
606 Eio_Done_Cb done_cb,
607 Eio_Error_Cb error_cb,
608 const void *data)
609 {
610 Eio_File_Direct_Ls *async;
611
612 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
613 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
614 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
615
616 async = eio_common_alloc(sizeof(Eio_File_Direct_Ls));
617 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
618
619 async->ls.directory = eina_stringshare_add(dir);
620 async->filter_cb = filter_cb;
621 if (main_internal_cb)
622 {
623 async->main_internal_cb = main_internal_cb;
624 async->ls.gather = EINA_TRUE;
625 }
626 else
627 {
628 async->main_cb = main_cb;
629 }
630
631 if (!eio_long_file_set(&async->ls.common,
632 done_cb,
633 error_cb,
634 data,
635 _eio_file_direct_heavy,
636 _eio_direct_notify,
637 eio_async_end,
638 eio_async_error))
639 return NULL;
640
641 return &async->ls.common;
642 }
643
644 EAPI Eio_File *
eio_file_direct_ls(const char * dir,Eio_Filter_Direct_Cb filter_cb,Eio_Main_Direct_Cb main_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)645 eio_file_direct_ls(const char *dir,
646 Eio_Filter_Direct_Cb filter_cb,
647 Eio_Main_Direct_Cb main_cb,
648 Eio_Done_Cb done_cb,
649 Eio_Error_Cb error_cb,
650 const void *data)
651 {
652 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
653
654 return _eio_file_direct_internal_ls(dir, filter_cb, main_cb, NULL, done_cb, error_cb, data);
655 }
656
657 Eio_File *
_eio_file_direct_ls(const char * dir,Eio_Array_Cb main_internal_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)658 _eio_file_direct_ls(const char *dir,
659 Eio_Array_Cb main_internal_cb,
660 Eio_Done_Cb done_cb,
661 Eio_Error_Cb error_cb,
662 const void *data)
663 {
664 EINA_SAFETY_ON_NULL_RETURN_VAL(main_internal_cb, NULL);
665
666 return _eio_file_direct_internal_ls(dir, NULL, NULL, main_internal_cb, done_cb, error_cb, data);
667 }
668
669 static Eio_File *
_eio_file_stat_internal_ls(const char * dir,Eio_Filter_Direct_Cb filter_cb,Eio_Main_Direct_Cb main_cb,Eio_Array_Cb main_internal_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)670 _eio_file_stat_internal_ls(const char *dir,
671 Eio_Filter_Direct_Cb filter_cb,
672 Eio_Main_Direct_Cb main_cb,
673 Eio_Array_Cb main_internal_cb,
674 Eio_Done_Cb done_cb,
675 Eio_Error_Cb error_cb,
676 const void *data)
677 {
678 Eio_File_Direct_Ls *async;
679
680 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
681 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
682 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
683
684 async = eio_common_alloc(sizeof(Eio_File_Direct_Ls));
685 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
686
687 async->ls.directory = eina_stringshare_add(dir);
688 async->filter_cb = filter_cb;
689 if (main_internal_cb)
690 {
691 async->main_internal_cb = main_internal_cb;
692 async->ls.gather = EINA_TRUE;
693 }
694 else
695 {
696 async->main_cb = main_cb;
697 }
698
699 if (!eio_long_file_set(&async->ls.common,
700 done_cb,
701 error_cb,
702 data,
703 _eio_file_stat_heavy,
704 _eio_direct_notify,
705 eio_async_end,
706 eio_async_error))
707 return NULL;
708
709 return &async->ls.common;
710 }
711
712 EAPI Eio_File *
eio_file_stat_ls(const char * dir,Eio_Filter_Direct_Cb filter_cb,Eio_Main_Direct_Cb main_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)713 eio_file_stat_ls(const char *dir,
714 Eio_Filter_Direct_Cb filter_cb,
715 Eio_Main_Direct_Cb main_cb,
716 Eio_Done_Cb done_cb,
717 Eio_Error_Cb error_cb,
718 const void *data)
719 {
720 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
721
722 return _eio_file_stat_internal_ls(dir, filter_cb, main_cb, NULL, done_cb, error_cb, data);
723 }
724
725 Eio_File *
_eio_file_stat_ls(const char * dir,Eio_Array_Cb main_internal_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)726 _eio_file_stat_ls(const char *dir,
727 Eio_Array_Cb main_internal_cb,
728 Eio_Done_Cb done_cb,
729 Eio_Error_Cb error_cb,
730 const void *data)
731 {
732 EINA_SAFETY_ON_NULL_RETURN_VAL(main_internal_cb, NULL);
733
734 return _eio_file_stat_internal_ls(dir, NULL, NULL, main_internal_cb, done_cb, error_cb, data);
735 }
736
737 EAPI Eina_Bool
eio_file_cancel(Eio_File * ls)738 eio_file_cancel(Eio_File *ls)
739 {
740 if (!ls) return EINA_FALSE;
741 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, EINA_FALSE);
742 // ensure callbacks are not called aftera cancel otherwise bad things
743 // happen higher up the stack - you cant stop these being caleld even if
744 // the dataptr they are passed has been freed or invalidated. being unable
745 // to stop future cb's and cancel them is BAD.
746 ls->error_cb = NULL;;
747 ls->done_cb = NULL;
748 return ecore_thread_cancel(ls->thread);
749 }
750
751 EAPI Eina_Bool
eio_file_check(Eio_File * ls)752 eio_file_check(Eio_File *ls)
753 {
754 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, EINA_TRUE);
755 return ecore_thread_check(ls->thread);
756 }
757
758 EAPI void *
eio_file_container_get(Eio_File * ls)759 eio_file_container_get(Eio_File *ls)
760 {
761 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, NULL);
762 return ls->container;
763 }
764
765 EAPI Eina_Bool
eio_file_associate_add(Eio_File * ls,const char * key,const void * data,Eina_Free_Cb free_cb)766 eio_file_associate_add(Eio_File *ls,
767 const char *key,
768 const void *data, Eina_Free_Cb free_cb)
769 {
770 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, EINA_FALSE);
771 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
772 /* FIXME: Check if we are in the right worker thread */
773 if (!ls->worker.associated)
774 ls->worker.associated = eina_hash_string_small_new(eio_associate_free);
775
776 return eina_hash_add(ls->worker.associated,
777 key,
778 eio_associate_malloc(data, free_cb));
779 }
780
781 EAPI Eina_Bool
eio_file_associate_direct_add(Eio_File * ls,const char * key,const void * data,Eina_Free_Cb free_cb)782 eio_file_associate_direct_add(Eio_File *ls,
783 const char *key,
784 const void *data, Eina_Free_Cb free_cb)
785 {
786 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, EINA_FALSE);
787 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
788 /* FIXME: Check if we are in the right worker thread */
789 if (!ls->worker.associated)
790 ls->worker.associated = eina_hash_string_small_new(eio_associate_free);
791
792 return eina_hash_direct_add(ls->worker.associated,
793 key,
794 eio_associate_malloc(data, free_cb));
795 }
796
797 EAPI void *
eio_file_associate_find(Eio_File * ls,const char * key)798 eio_file_associate_find(Eio_File *ls, const char *key)
799 {
800 Eio_File_Associate *search;
801
802 EINA_SAFETY_ON_NULL_RETURN_VAL(ls, NULL);
803 EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
804 if (!ls->main.associated)
805 return NULL;
806
807 search = eina_hash_find(ls->main.associated, key);
808 if (!search) return NULL;
809 return search->data;
810 }
811
812 EAPI Eio_File *
eio_file_copy(const char * source,const char * dest,Eio_Progress_Cb progress_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)813 eio_file_copy(const char *source,
814 const char *dest,
815 Eio_Progress_Cb progress_cb,
816 Eio_Done_Cb done_cb,
817 Eio_Error_Cb error_cb,
818 const void *data)
819 {
820 Eio_File_Progress *copy;
821
822 EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL);
823 EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL);
824 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
825 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
826
827 copy = eio_common_alloc(sizeof(Eio_File_Progress));
828 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, NULL);
829
830 copy->op = EIO_FILE_COPY;
831 copy->progress_cb = progress_cb;
832 copy->source = eina_stringshare_add(source);
833 copy->dest = eina_stringshare_add(dest);
834
835 if (!eio_long_file_set(©->common,
836 done_cb,
837 error_cb,
838 data,
839 _eio_file_copy_heavy,
840 _eio_file_copy_notify,
841 _eio_file_copy_end,
842 _eio_file_copy_error))
843 return NULL;
844
845 return ©->common;
846 }
847
848 EAPI Eio_File *
eio_file_move(const char * source,const char * dest,Eio_Progress_Cb progress_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)849 eio_file_move(const char *source,
850 const char *dest,
851 Eio_Progress_Cb progress_cb,
852 Eio_Done_Cb done_cb,
853 Eio_Error_Cb error_cb,
854 const void *data)
855 {
856 Eio_File_Move *move;
857
858 EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL);
859 EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL);
860 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
861 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
862
863 move = eio_common_alloc(sizeof(Eio_File_Move));
864 EINA_SAFETY_ON_NULL_RETURN_VAL(move, NULL);
865
866 move->progress.op = EIO_FILE_MOVE;
867 move->progress.progress_cb = progress_cb;
868 move->progress.source = eina_stringshare_add(source);
869 move->progress.dest = eina_stringshare_add(dest);
870 move->copy = NULL;
871
872 if (!eio_long_file_set(&move->progress.common,
873 done_cb,
874 error_cb,
875 data,
876 _eio_file_move_heavy,
877 _eio_file_move_notify,
878 _eio_file_move_end,
879 _eio_file_move_error))
880 return NULL;
881
882 return &move->progress.common;
883 }
884