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