1 /* EIO - EFL data type library
2 * Copyright (C) 2011 Enlightenment Developers:
3 * Cedric Bail <cedric.bail@free.fr>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library;
17 * if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "eio_private.h"
21 #include "Eio.h"
22
23 /*============================================================================*
24 * Local *
25 *============================================================================*/
26
27 /**
28 * @cond LOCAL
29 */
30
31 static void
_eio_ls_xattr_heavy(void * data,Ecore_Thread * thread)32 _eio_ls_xattr_heavy(void *data, Ecore_Thread *thread)
33 {
34 Eio_File_Char_Ls *async = data;
35 Eina_Iterator *it;
36 Eina_List *pack = NULL;
37 const char *tmp;
38 double start;
39
40 it = eina_xattr_ls(async->ls.directory);
41 if (!it) return;
42
43 eio_file_container_set(&async->ls.common, eina_iterator_container_get(it));
44
45 start = ecore_time_get();
46
47 EINA_ITERATOR_FOREACH(it, tmp)
48 {
49 Eina_Bool filter = EINA_TRUE;
50
51 if (async->filter_cb)
52 {
53 filter = async->filter_cb((void*) async->ls.common.data,
54 &async->ls.common,
55 tmp);
56 }
57
58 if (filter)
59 {
60 Eio_File_Char *send_fc;
61
62 send_fc = eio_char_malloc();
63 if (!send_fc) goto on_error;
64
65 send_fc->filename = eina_stringshare_add(tmp);
66 send_fc->associated = async->ls.common.worker.associated;
67 async->ls.common.worker.associated = NULL;
68
69 pack = eina_list_append(pack, send_fc);
70 }
71 else
72 {
73 on_error:
74 if (async->ls.common.worker.associated)
75 {
76 eina_hash_free(async->ls.common.worker.associated);
77 async->ls.common.worker.associated = NULL;
78 }
79 }
80
81 pack = eio_pack_send(thread, pack, &start);
82
83 if (ecore_thread_check(thread))
84 break;
85 }
86
87 if (pack) ecore_thread_feedback(thread, pack);
88
89 async->ls.ls = it;
90 }
91
92 static void
_eio_file_xattr_get(void * data,Ecore_Thread * thread)93 _eio_file_xattr_get(void *data, Ecore_Thread *thread)
94 {
95 Eio_File_Xattr *async = data;
96 Eina_Bool failure = EINA_FALSE;
97 const char *file;
98 const char *attribute;
99
100 file = async->path;
101 attribute = async->attribute;
102
103 switch (async->op)
104 {
105 case EIO_XATTR_DATA:
106 async->todo.xdata.xattr_size = 0;
107 async->todo.xdata.xattr_data = NULL;
108
109 async->todo.xdata.xattr_data = eina_xattr_get(file, attribute, &async->todo.xdata.xattr_size);
110 if (!async->todo.xdata.xattr_data) failure = EINA_TRUE;
111 break;
112 case EIO_XATTR_STRING:
113 async->todo.xstring.xattr_string = eina_xattr_string_get(file, attribute);
114 if (!async->todo.xstring.xattr_string) failure = EINA_TRUE;
115 break;
116 case EIO_XATTR_DOUBLE:
117 failure = !eina_xattr_double_get(file, attribute, &async->todo.xdouble.xattr_double);
118 break;
119 case EIO_XATTR_INT:
120 failure = !eina_xattr_int_get(file, attribute, &async->todo.xint.xattr_int);
121 break;
122 }
123
124 if (failure)
125 ecore_thread_cancel(thread);
126 }
127
128 static void
_eio_file_xattr_free(Eio_File_Xattr * async)129 _eio_file_xattr_free(Eio_File_Xattr *async)
130 {
131 eina_stringshare_del(async->path);
132 eina_stringshare_del(async->attribute);
133 if (!async->set)
134 {
135 if (async->op == EIO_XATTR_DATA) free(async->todo.xdata.xattr_data);
136 if (async->op == EIO_XATTR_STRING) free(async->todo.xstring.xattr_string);
137 }
138 eio_file_free(&async->common);
139 }
140
141 static void
_eio_file_xattr_get_done(void * data,Ecore_Thread * thread EINA_UNUSED)142 _eio_file_xattr_get_done(void *data, Ecore_Thread *thread EINA_UNUSED)
143 {
144 Eio_File_Xattr *async = data;
145
146 switch (async->op)
147 {
148 case EIO_XATTR_DATA:
149 if (async->todo.xdata.done_cb)
150 async->todo.xdata.done_cb((void *) async->common.data, &async->common, async->todo.xdata.xattr_data, async->todo.xdata.xattr_size);
151 break;
152 case EIO_XATTR_STRING:
153 if (async->todo.xstring.done_cb)
154 async->todo.xstring.done_cb((void *) async->common.data, &async->common, async->todo.xstring.xattr_string);
155 break;
156 case EIO_XATTR_DOUBLE:
157 if (async->todo.xdouble.done_cb)
158 async->todo.xdouble.done_cb((void *) async->common.data, &async->common, async->todo.xdouble.xattr_double);
159 break;
160 case EIO_XATTR_INT:
161 if (async->todo.xint.done_cb)
162 async->todo.xint.done_cb((void *) async->common.data, &async->common, async->todo.xint.xattr_int);
163 break;
164 }
165
166 _eio_file_xattr_free(async);
167 }
168
169 static void
_eio_file_xattr_get_error(void * data,Ecore_Thread * thread EINA_UNUSED)170 _eio_file_xattr_get_error(void *data, Ecore_Thread *thread EINA_UNUSED)
171 {
172 Eio_File_Xattr *async = data;
173
174 eio_file_error(&async->common);
175 _eio_file_xattr_free(async);
176 }
177
178 static void
_eio_file_xattr_set(void * data,Ecore_Thread * thread)179 _eio_file_xattr_set(void *data, Ecore_Thread *thread)
180 {
181 Eio_File_Xattr *async = data;
182 const char *file;
183 const char *attribute;
184 Eina_Xattr_Flags flags;
185 Eina_Bool failure = EINA_FALSE;
186
187 file = async->path;
188 attribute = async->attribute;
189 flags = async->flags;
190
191 switch (async->op)
192 {
193 case EIO_XATTR_DATA:
194 failure = !eina_xattr_set(file, attribute, async->todo.xdata.xattr_data, async->todo.xdata.xattr_size, flags);
195 async->common.length = async->todo.xdata.xattr_size;
196 break;
197 case EIO_XATTR_STRING:
198 failure = !eina_xattr_string_set(file, attribute, async->todo.xstring.xattr_string, flags);
199 async->common.length = strlen(async->todo.xstring.xattr_string) + 1;
200 break;
201 case EIO_XATTR_DOUBLE:
202 failure = !eina_xattr_double_set(file, attribute, async->todo.xdouble.xattr_double, flags);
203 async->common.length = sizeof (double);
204 break;
205 case EIO_XATTR_INT:
206 failure = !eina_xattr_int_set(file, attribute, async->todo.xint.xattr_int, flags);
207 async->common.length = sizeof (int);
208 break;
209 }
210
211 if (failure) eio_file_thread_error(&async->common, thread);
212 }
213
214 static void
_eio_file_xattr_set_done(void * data,Ecore_Thread * thread)215 _eio_file_xattr_set_done(void *data, Ecore_Thread *thread)
216 {
217 Eio_File_Xattr *async = data;
218
219 if (!ecore_thread_check(thread))
220 {
221 if (async->common.done_cb)
222 async->common.done_cb((void*) async->common.data, &async->common);
223 }
224
225 _eio_file_xattr_free(async);
226 }
227
228 static void
_eio_file_xattr_set_error(void * data,Ecore_Thread * thread EINA_UNUSED)229 _eio_file_xattr_set_error(void *data, Ecore_Thread *thread EINA_UNUSED)
230 {
231 Eio_File_Xattr *async = data;
232
233 eio_file_error(&async->common);
234 _eio_file_xattr_free(async);
235 }
236
237 static Eio_File *
_eio_file_xattr_setup_get(Eio_File_Xattr * async,const char * path,const char * attribute,Eio_Error_Cb error_cb,const void * data)238 _eio_file_xattr_setup_get(Eio_File_Xattr *async,
239 const char *path,
240 const char *attribute,
241 Eio_Error_Cb error_cb,
242 const void *data)
243 {
244 async->path = eina_stringshare_add(path);
245 async->attribute = eina_stringshare_add(attribute);
246 async->set = EINA_FALSE;
247
248 if (!eio_file_set(&async->common,
249 NULL,
250 error_cb,
251 data,
252 _eio_file_xattr_get,
253 _eio_file_xattr_get_done,
254 _eio_file_xattr_get_error))
255 return NULL;
256
257 return &async->common;
258 }
259
260 static Eio_File *
_eio_file_xattr_setup_set(Eio_File_Xattr * async,const char * path,const char * attribute,Eina_Xattr_Flags flags,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)261 _eio_file_xattr_setup_set(Eio_File_Xattr *async,
262 const char *path,
263 const char *attribute,
264 Eina_Xattr_Flags flags,
265 Eio_Done_Cb done_cb,
266 Eio_Error_Cb error_cb,
267 const void *data)
268 {
269 async->path = eina_stringshare_add(path);
270 async->attribute = eina_stringshare_add(attribute);
271 async->flags = flags;
272 async->set = EINA_TRUE;
273
274 if (!eio_file_set(&async->common,
275 done_cb,
276 error_cb,
277 data,
278 _eio_file_xattr_set,
279 _eio_file_xattr_set_done,
280 _eio_file_xattr_set_error))
281 return NULL;
282
283 return &async->common;
284 }
285
286 /**
287 * @endcond
288 */
289
290
291 /*============================================================================*
292 * Global *
293 *============================================================================*/
294
295 /**
296 * @cond LOCAL
297 */
298
299 /**
300 * @endcond
301 */
302
303
304 /*============================================================================*
305 * API *
306 *============================================================================*/
307
308 static Eio_File *
_eio_file_internal_xattr(const char * path,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)309 _eio_file_internal_xattr(const char *path,
310 Eio_Filter_Cb filter_cb,
311 Eio_Main_Cb main_cb,
312 Eio_Array_Cb main_internal_cb,
313 Eio_Done_Cb done_cb,
314 Eio_Error_Cb error_cb,
315 const void *data)
316 {
317 Eio_File_Char_Ls *async;
318
319 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
320 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
321 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
322
323 async = eio_common_alloc(sizeof (Eio_File_Char_Ls));
324 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
325
326 async->ls.directory = eina_stringshare_add(path);
327 async->filter_cb = filter_cb;
328
329 if (main_internal_cb)
330 {
331 async->main_internal_cb = main_internal_cb;
332 async->ls.gather = EINA_TRUE;
333 }
334 else
335 {
336 async->main_cb = main_cb;
337 }
338
339 if (!eio_long_file_set(&async->ls.common,
340 done_cb,
341 error_cb,
342 data,
343 _eio_ls_xattr_heavy,
344 _eio_string_notify,
345 eio_async_end,
346 eio_async_error))
347 return NULL;
348
349 return &async->ls.common;
350 }
351
352 EAPI Eio_File *
eio_file_xattr(const char * path,Eio_Filter_Cb filter_cb,Eio_Main_Cb main_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)353 eio_file_xattr(const char *path,
354 Eio_Filter_Cb filter_cb,
355 Eio_Main_Cb main_cb,
356 Eio_Done_Cb done_cb,
357 Eio_Error_Cb error_cb,
358 const void *data)
359 {
360 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
361
362 return _eio_file_internal_xattr(path, filter_cb, main_cb, NULL, done_cb, error_cb, data);
363 }
364
365 Eio_File *
_eio_file_xattr(const char * path,Eio_Array_Cb main_internal_cb,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)366 _eio_file_xattr(const char *path,
367 Eio_Array_Cb main_internal_cb,
368 Eio_Done_Cb done_cb,
369 Eio_Error_Cb error_cb,
370 const void *data)
371 {
372 EINA_SAFETY_ON_NULL_RETURN_VAL(main_internal_cb, NULL);
373
374 return _eio_file_internal_xattr(path, NULL, NULL, main_internal_cb, done_cb, error_cb, data);
375 }
376
377 EAPI Eio_File *
eio_file_xattr_get(const char * path,const char * attribute,Eio_Done_Data_Cb done_cb,Eio_Error_Cb error_cb,const void * data)378 eio_file_xattr_get(const char *path,
379 const char *attribute,
380 Eio_Done_Data_Cb done_cb,
381 Eio_Error_Cb error_cb,
382 const void *data)
383 {
384 Eio_File_Xattr *async;
385
386 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
387 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
388 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
389 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
390
391 async = malloc(sizeof (Eio_File_Xattr));
392 if (!async) return NULL;
393
394 async->op = EIO_XATTR_DATA;
395 async->todo.xdata.done_cb = done_cb;
396
397 return _eio_file_xattr_setup_get(async, path, attribute, error_cb, data);
398 }
399
400 EAPI Eio_File *
eio_file_xattr_string_get(const char * path,const char * attribute,Eio_Done_String_Cb done_cb,Eio_Error_Cb error_cb,const void * data)401 eio_file_xattr_string_get(const char *path,
402 const char *attribute,
403 Eio_Done_String_Cb done_cb,
404 Eio_Error_Cb error_cb,
405 const void *data)
406 {
407 Eio_File_Xattr *async;
408
409 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
410 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
411 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
412 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
413
414 async = malloc(sizeof (Eio_File_Xattr));
415 if (!async) return NULL;
416
417 async->op = EIO_XATTR_STRING;
418 async->todo.xstring.done_cb = done_cb;
419
420 return _eio_file_xattr_setup_get(async, path, attribute, error_cb, data);
421 }
422
423 EAPI Eio_File *
eio_file_xattr_double_get(const char * path,const char * attribute,Eio_Done_Double_Cb done_cb,Eio_Error_Cb error_cb,const void * data)424 eio_file_xattr_double_get(const char *path,
425 const char *attribute,
426 Eio_Done_Double_Cb done_cb,
427 Eio_Error_Cb error_cb,
428 const void *data)
429 {
430 Eio_File_Xattr *async;
431
432 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
433 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
434 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
435 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
436
437 async = malloc(sizeof (Eio_File_Xattr));
438 if (!async) return NULL;
439
440 async->op = EIO_XATTR_DOUBLE;
441 async->todo.xdouble.done_cb = done_cb;
442
443 return _eio_file_xattr_setup_get(async, path, attribute, error_cb, data);
444 }
445
446 EAPI Eio_File *
eio_file_xattr_int_get(const char * path,const char * attribute,Eio_Done_Int_Cb done_cb,Eio_Error_Cb error_cb,const void * data)447 eio_file_xattr_int_get(const char *path,
448 const char *attribute,
449 Eio_Done_Int_Cb done_cb,
450 Eio_Error_Cb error_cb,
451 const void *data)
452 {
453 Eio_File_Xattr *async;
454
455 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
456 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
457 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
458 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
459
460 async = malloc(sizeof (Eio_File_Xattr));
461 if (!async) return NULL;
462
463 async->op = EIO_XATTR_INT;
464 async->todo.xint.done_cb = done_cb;
465
466 return _eio_file_xattr_setup_get(async, path, attribute, error_cb, data);
467 }
468
469 EAPI Eio_File *
eio_file_xattr_set(const char * path,const char * attribute,const char * xattr_data,unsigned int xattr_size,Eina_Xattr_Flags flags,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)470 eio_file_xattr_set(const char *path,
471 const char *attribute,
472 const char *xattr_data,
473 unsigned int xattr_size,
474 Eina_Xattr_Flags flags,
475 Eio_Done_Cb done_cb,
476 Eio_Error_Cb error_cb,
477 const void *data)
478 {
479 Eio_File_Xattr *async;
480
481 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
482 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
483 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
484 EINA_SAFETY_ON_NULL_RETURN_VAL(xattr_data, NULL);
485 EINA_SAFETY_ON_FALSE_RETURN_VAL(xattr_size, NULL);
486 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
487
488 async = malloc(sizeof (Eio_File_Xattr) + xattr_size);
489 if (!async) return NULL;
490
491 async->op = EIO_XATTR_DATA;
492 async->todo.xdata.xattr_size = xattr_size;
493 async->todo.xdata.xattr_data = (char*) (async + 1);
494 memcpy(async->todo.xdata.xattr_data, xattr_data, xattr_size);
495
496 return _eio_file_xattr_setup_set(async, path, attribute, flags, done_cb, error_cb, data);
497 }
498
499 EAPI Eio_File *
eio_file_xattr_string_set(const char * path,const char * attribute,const char * xattr_string,Eina_Xattr_Flags flags,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)500 eio_file_xattr_string_set(const char *path,
501 const char *attribute,
502 const char *xattr_string,
503 Eina_Xattr_Flags flags,
504 Eio_Done_Cb done_cb,
505 Eio_Error_Cb error_cb,
506 const void *data)
507 {
508 Eio_File_Xattr *async;
509 int length;
510
511 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
512 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
513 EINA_SAFETY_ON_NULL_RETURN_VAL(xattr_string, NULL);
514 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
515 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
516
517 async = malloc(sizeof (Eio_File_Xattr));
518 if (!async) return NULL;
519
520 length = strlen(xattr_string) + 1;
521
522 async->op = EIO_XATTR_STRING;
523 async->todo.xstring.xattr_string = malloc(length);
524 if (!async->todo.xstring.xattr_string)
525 {
526 free(async);
527 return NULL;
528 }
529 memcpy(async->todo.xstring.xattr_string, xattr_string, length);
530
531 return _eio_file_xattr_setup_set(async, path, attribute, flags, done_cb, error_cb, data);
532 }
533
534 EAPI Eio_File *
eio_file_xattr_double_set(const char * path,const char * attribute,double xattr_double,Eina_Xattr_Flags flags,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)535 eio_file_xattr_double_set(const char *path,
536 const char *attribute,
537 double xattr_double,
538 Eina_Xattr_Flags flags,
539 Eio_Done_Cb done_cb,
540 Eio_Error_Cb error_cb,
541 const void *data)
542 {
543 Eio_File_Xattr *async;
544
545 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
546 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
547 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
548 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
549
550 async = malloc(sizeof (Eio_File_Xattr));
551 if (!async) return NULL;
552
553 async->op = EIO_XATTR_DOUBLE;
554 async->todo.xdouble.xattr_double = xattr_double;
555
556 return _eio_file_xattr_setup_set(async, path, attribute, flags, done_cb, error_cb, data);
557 }
558
559 EAPI Eio_File *
eio_file_xattr_int_set(const char * path,const char * attribute,int xattr_int,Eina_Xattr_Flags flags,Eio_Done_Cb done_cb,Eio_Error_Cb error_cb,const void * data)560 eio_file_xattr_int_set(const char *path,
561 const char *attribute,
562 int xattr_int,
563 Eina_Xattr_Flags flags,
564 Eio_Done_Cb done_cb,
565 Eio_Error_Cb error_cb,
566 const void *data)
567 {
568 Eio_File_Xattr *async;
569
570 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
571 EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL);
572 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
573 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
574
575 async = malloc(sizeof (Eio_File_Xattr));
576 if (!async) return NULL;
577
578 async->op = EIO_XATTR_INT;
579 async->todo.xint.xattr_int = xattr_int;
580
581 return _eio_file_xattr_setup_set(async, path, attribute, flags, done_cb, error_cb, data);
582 }
583