summaryrefslogtreecommitdiff
path: root/src/lib/eio/eio_single.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/eio/eio_single.c')
-rw-r--r--src/lib/eio/eio_single.c594
1 files changed, 594 insertions, 0 deletions
diff --git a/src/lib/eio/eio_single.c b/src/lib/eio/eio_single.c
new file mode 100644
index 0000000..d80dd84
--- /dev/null
+++ b/src/lib/eio/eio_single.c
@@ -0,0 +1,594 @@
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#include "eio_private.h"
22#include "Eio.h"
23
24/*============================================================================*
25 * Local *
26 *============================================================================*/
27
28/**
29 * @cond LOCAL
30 */
31
32static void
33_eio_file_mkdir(void *data, Ecore_Thread *thread)
34{
35 Eio_File_Mkdir *m = data;
36
37 if (mkdir(m->path, m->mode) != 0)
38 eio_file_thread_error(&m->common, thread);
39}
40
41static void
42_eio_mkdir_free(Eio_File_Mkdir *m)
43{
44 eina_stringshare_del(m->path);
45 eio_file_free(&m->common);
46}
47
48static void
49_eio_file_mkdir_done(void *data, Ecore_Thread *thread EINA_UNUSED)
50{
51 Eio_File_Mkdir *m = data;
52
53 if (m->common.done_cb)
54 m->common.done_cb((void*) m->common.data, &m->common);
55
56 _eio_mkdir_free(m);
57}
58
59static void
60_eio_file_mkdir_error(void *data, Ecore_Thread *thread EINA_UNUSED)
61{
62 Eio_File_Mkdir *m = data;
63
64 eio_file_error(&m->common);
65 _eio_mkdir_free(m);
66}
67
68static void
69_eio_file_unlink(void *data, Ecore_Thread *thread)
70{
71 Eio_File_Unlink *l = data;
72
73 if (unlink(l->path) != 0)
74 eio_file_thread_error(&l->common, thread);
75}
76
77static void
78_eio_unlink_free(Eio_File_Unlink *l)
79{
80 eina_stringshare_del(l->path);
81 eio_file_free(&l->common);
82}
83
84static void
85_eio_file_unlink_done(void *data, Ecore_Thread *thread EINA_UNUSED)
86{
87 Eio_File_Unlink *l = data;
88
89 if (l->common.done_cb)
90 l->common.done_cb((void*) l->common.data, &l->common);
91
92 _eio_unlink_free(l);
93}
94
95static void
96_eio_file_unlink_error(void *data, Ecore_Thread *thread EINA_UNUSED)
97{
98 Eio_File_Unlink *l = data;
99
100 eio_file_error(&l->common);
101 _eio_unlink_free(l);
102}
103
104static void
105_eio_file_struct_2_eina(Eina_Stat *es, _eio_stat_t *st)
106{
107 es->dev = st->st_dev;
108 es->ino = st->st_ino;
109 es->mode = st->st_mode;
110 es->nlink = st->st_nlink;
111 es->uid = st->st_uid;
112 es->gid = st->st_gid;
113 es->rdev = st->st_rdev;
114 es->size = st->st_size;
115#ifdef _WIN32
116 es->blksize = 0;
117 es->blocks = 0;
118#else
119 es->blksize = st->st_blksize;
120 es->blocks = st->st_blocks;
121#endif
122 es->atime = st->st_atime;
123 es->mtime = st->st_mtime;
124 es->ctime = st->st_ctime;
125#ifdef _STAT_VER_LINUX
126# if (defined __USE_MISC && defined st_mtime)
127 es->atimensec = st->st_atim.tv_nsec;
128 es->mtimensec = st->st_mtim.tv_nsec;
129 es->ctimensec = st->st_ctim.tv_nsec;
130# else
131 es->atimensec = st->st_atimensec;
132 es->mtimensec = st->st_mtimensec;
133 es->ctimensec = st->st_ctimensec;
134# endif
135#else
136 es->atimensec = 0;
137 es->mtimensec = 0;
138 es->ctimensec = 0;
139#endif
140}
141
142static void
143_eio_file_stat(void *data, Ecore_Thread *thread)
144{
145 Eio_File_Stat *s = data;
146 _eio_stat_t buf;
147
148 if (_eio_stat(s->path, &buf) != 0)
149 eio_file_thread_error(&s->common, thread);
150
151 _eio_file_struct_2_eina(&s->buffer, &buf);
152}
153
154#ifdef HAVE_LSTAT
155static void
156_eio_file_lstat(void *data, Ecore_Thread *thread)
157{
158 Eio_File_Stat *s = data;
159 struct stat buf;
160
161 if (lstat(s->path, &buf) != 0)
162 eio_file_thread_error(&s->common, thread);
163
164 _eio_file_struct_2_eina(&s->buffer, &buf);
165}
166#endif
167
168static void
169_eio_stat_free(Eio_File_Stat *s)
170{
171 eina_stringshare_del(s->path);
172 eio_file_free(&s->common);
173}
174
175static void
176_eio_file_stat_done(void *data, Ecore_Thread *thread EINA_UNUSED)
177{
178 Eio_File_Stat *s = data;
179
180 if (s->done_cb)
181 s->done_cb((void*) s->common.data, &s->common, &s->buffer);
182
183 _eio_stat_free(s);
184}
185
186static void
187_eio_file_stat_error(void *data, Ecore_Thread *thread EINA_UNUSED)
188{
189 Eio_File_Stat *s = data;
190
191 eio_file_error(&s->common);
192 _eio_stat_free(s);
193}
194
195static void
196_eio_file_chmod(void *data, Ecore_Thread *thread)
197{
198 Eio_File_Chmod *ch = data;
199
200 if (chmod(ch->path, ch->mode) != 0)
201 eio_file_thread_error(&ch->common, thread);
202}
203
204static void
205_eio_file_chown(void *data, Ecore_Thread *thread)
206{
207#ifdef _WIN32
208 /* FIXME:
209 * look at http://wwwthep.physik.uni-mainz.de/~frink/chown/readme.html
210 */
211 (void)data;
212 (void)thread;
213#else
214 Eio_File_Chown *own = data;
215 char *tmp;
216 uid_t owner = -1;
217 gid_t group = -1;
218
219 own->common.error = 0;
220
221 if (own->user)
222 {
223 owner = strtol(own->user, &tmp, 10);
224
225 if (*tmp != '\0')
226 {
227 struct passwd *pw = NULL;
228
229 own->common.error = EIO_FILE_GETPWNAM;
230
231 pw = getpwnam(own->user);
232 if (!pw) goto on_error;
233
234 owner = pw->pw_uid;
235 }
236 }
237
238 if (own->group)
239 {
240 group = strtol(own->group, &tmp, 10);
241
242 if (*tmp != '\0')
243 {
244 struct group *grp = NULL;
245
246 own->common.error = EIO_FILE_GETGRNAM;
247
248 grp = getgrnam(own->group);
249 if (!grp) goto on_error;
250
251 group = grp->gr_gid;
252 }
253 }
254
255 if (owner == (uid_t) -1 && group == (gid_t) -1)
256 goto on_error;
257
258 if (chown(own->path, owner, group) != 0)
259 eio_file_thread_error(&own->common, thread);
260
261 return ;
262
263 on_error:
264 ecore_thread_cancel(thread);
265 return ;
266#endif
267}
268
269static void
270_eio_chown_free(Eio_File_Chown *ch)
271{
272 if (ch->user) eina_stringshare_del(ch->user);
273 if (ch->group) eina_stringshare_del(ch->group);
274 eina_stringshare_del(ch->path);
275 eio_file_free(&ch->common);
276}
277
278static void
279_eio_file_chown_done(void *data, Ecore_Thread *thread EINA_UNUSED)
280{
281 Eio_File_Chown *ch = data;
282
283 if (ch->common.done_cb)
284 ch->common.done_cb((void*) ch->common.data, &ch->common);
285
286 _eio_chown_free(ch);
287}
288
289static void
290_eio_file_chown_error(void *data, Ecore_Thread *thread EINA_UNUSED)
291{
292 Eio_File_Chown *ch = data;
293
294 eio_file_error(&ch->common);
295 _eio_chown_free(ch);
296}
297
298/**
299 * @endcond
300 */
301
302/*============================================================================*
303 * Global *
304 *============================================================================*/
305
306/**
307 * @cond LOCAL
308 */
309
310void
311eio_file_error(Eio_File *common)
312{
313 if (common->error_cb)
314 common->error_cb((void*) common->data, common, common->error);
315}
316
317void
318eio_file_thread_error(Eio_File *common, Ecore_Thread *thread)
319{
320 common->error = errno;
321 ecore_thread_cancel(thread);
322}
323
324void
325eio_file_free(Eio_File *common)
326{
327 if (common->worker.associated)
328 eina_hash_free(common->worker.associated);
329 if (common->main.associated)
330 eina_hash_free(common->main.associated);
331 free(common);
332}
333
334Eina_Bool
335eio_long_file_set(Eio_File *common,
336 Eio_Done_Cb done_cb,
337 Eio_Error_Cb error_cb,
338 const void *data,
339 Ecore_Thread_Cb heavy_cb,
340 Ecore_Thread_Notify_Cb notify_cb,
341 Ecore_Thread_Cb end_cb,
342 Ecore_Thread_Cb cancel_cb)
343{
344 Ecore_Thread *thread;
345
346 common->done_cb = done_cb;
347 common->error_cb = error_cb;
348 common->data = data;
349 common->error = 0;
350 common->thread = NULL;
351 common->container = NULL;
352 common->worker.associated = NULL;
353 common->main.associated = NULL;
354
355 /* Be aware that ecore_thread_feedback_run could call cancel_cb if something goes wrong.
356 This means that common would be destroyed if thread == NULL.
357 */
358 thread = ecore_thread_feedback_run(heavy_cb,
359 notify_cb,
360 end_cb,
361 cancel_cb,
362 common,
363 EINA_FALSE);
364 if (thread) common->thread = thread;
365 return !!thread;
366}
367
368Eina_Bool
369eio_file_set(Eio_File *common,
370 Eio_Done_Cb done_cb,
371 Eio_Error_Cb error_cb,
372 const void *data,
373 Ecore_Thread_Cb job_cb,
374 Ecore_Thread_Cb end_cb,
375 Ecore_Thread_Cb cancel_cb)
376{
377 Ecore_Thread *thread;
378
379 common->done_cb = done_cb;
380 common->error_cb = error_cb;
381 common->data = data;
382 common->error = 0;
383 common->thread = NULL;
384 common->container = NULL;
385 common->worker.associated = NULL;
386 common->main.associated = NULL;
387
388 /* Be aware that ecore_thread_run could call cancel_cb if something goes wrong.
389 This means that common would be destroyed if thread == NULL.
390 */
391 thread = ecore_thread_run(job_cb, end_cb, cancel_cb, common);
392
393 if (thread) common->thread = thread;
394 return !!thread;
395}
396
397void
398eio_file_container_set(Eio_File *common, void *container)
399{
400 common->container = container;
401}
402
403/**
404 * @endcond
405 */
406
407
408/*============================================================================*
409 * API *
410 *============================================================================*/
411
412EAPI Eio_File *
413eio_file_direct_stat(const char *path,
414 Eio_Stat_Cb done_cb,
415 Eio_Error_Cb error_cb,
416 const void *data)
417{
418 Eio_File_Stat *s = NULL;
419
420 if (!path || !done_cb || !error_cb)
421 return NULL;
422
423 s = malloc(sizeof (Eio_File_Stat));
424 if (!s) return NULL;
425
426 s->path = eina_stringshare_add(path);
427 s->done_cb = done_cb;
428
429 if (!eio_file_set(&s->common,
430 NULL,
431 error_cb,
432 data,
433 _eio_file_stat,
434 _eio_file_stat_done,
435 _eio_file_stat_error))
436 /* THERE IS NO MEMLEAK HERE, ECORE_THREAD CANCEL CALLBACK HAS BEEN ALREADY CALLED
437 AND s HAS BEEN FREED, SAME FOR ALL CALL TO EIO_FILE_SET ! */
438 return NULL;
439
440 return &s->common;
441}
442
443EAPI Eio_File *
444eio_file_direct_lstat(const char *path,
445 Eio_Stat_Cb done_cb,
446 Eio_Error_Cb error_cb,
447 const void *data)
448{
449#ifdef HAVE_LSTAT
450 Eio_File_Stat *s = NULL;
451
452 if (!path || !done_cb || !error_cb)
453 return NULL;
454
455 s = malloc(sizeof (Eio_File_Stat));
456 if (!s) return NULL;
457
458 s->path = eina_stringshare_add(path);
459 s->done_cb = done_cb;
460
461 if (!eio_file_set(&s->common,
462 NULL,
463 error_cb,
464 data,
465 _eio_file_lstat,
466 _eio_file_stat_done,
467 _eio_file_stat_error))
468 return NULL;
469
470 return &s->common;
471#else
472 return eio_file_direct_stat(path, done_cb, error_cb, data);
473#endif
474}
475
476EAPI Eio_File *
477eio_file_unlink(const char *path,
478 Eio_Done_Cb done_cb,
479 Eio_Error_Cb error_cb,
480 const void *data)
481{
482 Eio_File_Unlink *l = NULL;
483
484 if (!path || !done_cb || !error_cb)
485 return NULL;
486
487 l = malloc(sizeof (Eio_File_Unlink));
488 if (!l) return NULL;
489
490 l->path = eina_stringshare_add(path);
491
492 if (!eio_file_set(&l->common,
493 done_cb,
494 error_cb,
495 data,
496 _eio_file_unlink,
497 _eio_file_unlink_done,
498 _eio_file_unlink_error))
499 return NULL;
500
501 return &l->common;
502}
503
504EAPI Eio_File *
505eio_file_mkdir(const char *path,
506 mode_t mode,
507 Eio_Done_Cb done_cb,
508 Eio_Error_Cb error_cb,
509 const void *data)
510{
511 Eio_File_Mkdir *r = NULL;
512
513 if (!path || !done_cb || !error_cb)
514 return NULL;
515
516 r = malloc(sizeof (Eio_File_Mkdir));
517 if (!r) return NULL;
518
519 r->path = eina_stringshare_add(path);
520 r->mode = mode;
521
522 if (!eio_file_set(&r->common,
523 done_cb,
524 error_cb,
525 data,
526 _eio_file_mkdir,
527 _eio_file_mkdir_done,
528 _eio_file_mkdir_error))
529 return NULL;
530
531 return &r->common;
532}
533
534EAPI Eio_File *
535eio_file_chmod(const char *path,
536 mode_t mode,
537 Eio_Done_Cb done_cb,
538 Eio_Error_Cb error_cb,
539 const void *data)
540{
541 Eio_File_Mkdir *r = NULL;
542
543 if (!path || !done_cb || !error_cb)
544 return NULL;
545
546 r = malloc(sizeof (Eio_File_Mkdir));
547 if (!r) return NULL;
548
549 r->path = eina_stringshare_add(path);
550 r->mode = mode;
551
552 if (!eio_file_set(&r->common,
553 done_cb,
554 error_cb,
555 data,
556 _eio_file_chmod,
557 _eio_file_mkdir_done,
558 _eio_file_mkdir_error))
559 return NULL;
560
561 return &r->common;
562}
563
564EAPI Eio_File *
565eio_file_chown(const char *path,
566 const char *user,
567 const char *group,
568 Eio_Done_Cb done_cb,
569 Eio_Error_Cb error_cb,
570 const void *data)
571{
572 Eio_File_Chown *c = NULL;
573
574 if (!path || !done_cb || !error_cb)
575 return NULL;
576
577 c = malloc(sizeof (Eio_File_Chown));
578 if (!c) return NULL;
579
580 c->path = eina_stringshare_add(path);
581 c->user = eina_stringshare_add(user);
582 c->group = eina_stringshare_add(group);
583
584 if (!eio_file_set(&c->common,
585 done_cb,
586 error_cb,
587 data,
588 _eio_file_chown,
589 _eio_file_chown_done,
590 _eio_file_chown_error))
591 return NULL;
592
593 return &c->common;
594}