summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-12-04 17:40:58 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-12-04 17:40:58 +0000
commit81c86b19f6b432c5d6701bd025d5b2cf308fba4c (patch)
tree44f76300c96fddf3be01d97afb3025227350ee92 /src
parent633e29c5a50fa1a1087df88d8d9859c79a83e486 (diff)
merge: eio + fix compilation on windows + minor fixes + po files
don't move eio to IN-EFL right now SVN revision: 80180
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile_Ecore_Evas.am4
-rw-r--r--src/Makefile_Eio.am50
-rw-r--r--src/lib/eio/Eio.h1190
-rw-r--r--src/lib/eio/eio_dir.c1001
-rw-r--r--src/lib/eio/eio_eet.c640
-rw-r--r--src/lib/eio/eio_file.c979
-rw-r--r--src/lib/eio/eio_inline_helper.x105
-rw-r--r--src/lib/eio/eio_main.c300
-rw-r--r--src/lib/eio/eio_map.c316
-rw-r--r--src/lib/eio/eio_monitor.c351
-rw-r--r--src/lib/eio/eio_monitor_inotify.c273
-rw-r--r--src/lib/eio/eio_monitor_poll.c354
-rw-r--r--src/lib/eio/eio_monitor_win32.c425
-rw-r--r--src/lib/eio/eio_private.h538
-rw-r--r--src/lib/eio/eio_single.c594
-rw-r--r--src/lib/eio/eio_xattr.c500
17 files changed, 7619 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2d2ae9e9c7..73ac3a9048 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -56,6 +56,7 @@ endif
56include Makefile_Ecore_Imf.am 56include Makefile_Ecore_Imf.am
57include Makefile_Ecore_Evas.am 57include Makefile_Ecore_Evas.am
58include Makefile_Embryo.am 58include Makefile_Embryo.am
59include Makefile_Eio.am
59 60
60.PHONY: benchmark examples 61.PHONY: benchmark examples
61 62
diff --git a/src/Makefile_Ecore_Evas.am b/src/Makefile_Ecore_Evas.am
index f38c31ae84..40036b753d 100644
--- a/src/Makefile_Ecore_Evas.am
+++ b/src/Makefile_Ecore_Evas.am
@@ -107,10 +107,10 @@ if HAVE_WIN32
107lib_ecore_evas_libecore_evas_la_CPPFLAGS += \ 107lib_ecore_evas_libecore_evas_la_CPPFLAGS += \
108-I$(top_srcdir)/src/lib/ecore_win32 \ 108-I$(top_srcdir)/src/lib/ecore_win32 \
109-I$(top_srcdir)/src/modules/evas/engines/software_ddraw \ 109-I$(top_srcdir)/src/modules/evas/engines/software_ddraw \
110-I$(top_srcdir)/src/modules/evas/engines/direct3d \ 110-I$(top_srcdir)/src/modules/evas/engines/software_gdi \
111-I$(top_builddir)/src/lib/ecore_win32 \ 111-I$(top_builddir)/src/lib/ecore_win32 \
112-I$(top_builddir)/src/modules/evas/engines/software_ddraw \ 112-I$(top_builddir)/src/modules/evas/engines/software_ddraw \
113-I$(top_builddir)/src/modules/evas/engines/direct3d 113-I$(top_builddir)/src/modules/evas/engines/software_gdi
114endif 114endif
115 115
116if HAVE_WINCE 116if HAVE_WINCE
diff --git a/src/Makefile_Eio.am b/src/Makefile_Eio.am
new file mode 100644
index 0000000000..93f4d25f93
--- /dev/null
+++ b/src/Makefile_Eio.am
@@ -0,0 +1,50 @@
1
2### Library
3
4lib_LTLIBRARIES += lib/eio/libeio.la
5
6installed_eiomainheadersdir = $(includedir)/eio-@VMAJ@
7dist_installed_eiomainheaders_DATA = lib/eio/Eio.h lib/eio/eio_inline_helper.x
8
9lib_eio_libeio_la_SOURCES = \
10lib/eio/eio_dir.c \
11lib/eio/eio_eet.c \
12lib/eio/eio_file.c \
13lib/eio/eio_main.c \
14lib/eio/eio_map.c \
15lib/eio/eio_monitor.c \
16lib/eio/eio_monitor_poll.c \
17lib/eio/eio_single.c \
18lib/eio/eio_xattr.c \
19lib/eio/eio_private.h
20
21if EIO_HAVE_INOTIFY
22lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_inotify.c
23else
24if EIO_HAVE_WINCHANGE
25lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_win32.c
26endif
27endif
28
29lib_eio_libeio_la_CPPFLAGS = \
30-I$(top_srcdir)/src/lib/eina \
31-I$(top_srcdir)/src/lib/eo \
32-I$(top_srcdir)/src/lib/eet \
33-I$(top_srcdir)/src/lib/ecore \
34-I$(top_srcdir)/src/lib/eio \
35-I$(top_builddir)/src/lib/eina \
36-I$(top_builddir)/src/lib/eo \
37-I$(top_builddir)/src/lib/eet \
38-I$(top_builddir)/src/lib/ecore \
39-I$(top_builddir)/src/lib/eio \
40-DEFL_EIO_BUILD \
41@EFL_CFLAGS@
42
43lib_eio_libeio_la_LIBADD = \
44lib/eina/libeina.la \
45lib/eo/libeo.la \
46lib/eet/libeet.la \
47lib/ecore/libecore.la \
48-lm
49
50lib_eio_libeio_la_LDFLAGS = -no-undefined -version-info @version_info@ @release_info@
diff --git a/src/lib/eio/Eio.h b/src/lib/eio/Eio.h
new file mode 100644
index 0000000000..cb791a0ebf
--- /dev/null
+++ b/src/lib/eio/Eio.h
@@ -0,0 +1,1190 @@
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#ifndef EIO_H__
23# define EIO_H__
24
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
28
29#include <Eina.h>
30#include <Eet.h>
31
32#ifdef EAPI
33# undef EAPI
34#endif
35
36#ifdef _WIN32
37# ifdef EFL_EIO_BUILD
38# ifdef DLL_EXPORT
39# define EAPI __declspec(dllexport)
40# else
41# define EAPI
42# endif /* ! DLL_EXPORT */
43# else
44# define EAPI __declspec(dllimport)
45# endif /* ! EFL_EIO_BUILD */
46#else
47# ifdef __GNUC__
48# if __GNUC__ >= 4
49# define EAPI __attribute__ ((visibility("default")))
50# else
51# define EAPI
52# endif
53# else
54# define EAPI
55# endif
56#endif /* ! _WIN32 */
57
58
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63#define EIO_VERSION_MAJOR 1
64#define EIO_VERSION_MINOR 8
65
66 /**
67 * @typedef Eio_Version
68 * Represents the current version of EIO
69 */
70 typedef struct _Eio_Version
71 {
72 int major; /**< Major version number */
73 int minor; /**< Minor version number */
74 int micro; /**< Micro version number */
75 int revision; /**< Revision number */
76 } Eio_Version;
77
78 EAPI extern Eio_Version *eio_version;
79
80/**
81 * @defgroup Eio_Group Eio Reference API
82 *
83 * @brief This is the core asynchronous input/output operation
84 *
85 * All the functions in this group perform input/output operations
86 * in a separate thread using the infrastructure provided by
87 * Ecore_Thread and Eina, this means that all functions here are non-blocking.
88 *
89 * The functions displayed here are used to make basic file operations, like
90 * listing the content of a directory, creating a new directory, etc.
91 *
92 * @{
93 */
94
95/**
96 * @enum _Eio_File_Op
97 *
98 * @brief Input/Output operations on files.
99 *
100 * This enum represents the operations that can be done.
101 */
102enum _Eio_File_Op
103{
104 EIO_FILE_COPY, /**< I/O operation is about a specific file copy */
105 EIO_FILE_MOVE, /**< I/O operation is about a specific file move */
106 EIO_DIR_COPY, /**< I/O operation is about a specific directory copy */
107 EIO_DIR_MOVE, /**< I/O operation is about a specific directory move */
108 /** I/O operation is about destroying a path:
109 * source will point to base path to be destroyed,
110 * and dest will point to to path destroyed by this I/O
111 */
112 EIO_UNLINK,
113 EIO_FILE_GETPWNAM, /**< I/O operation is trying to get uid from user name */
114 EIO_FILE_GETGRNAM /**< I/O operation is trying to get gid from user name */
115};
116
117/**
118 * @typedef Eio_File_Op
119 * Input/Output operations on files.
120 */
121typedef enum _Eio_File_Op Eio_File_Op;
122
123/**
124 * @typedef Eio_File
125 * Generic asynchronous I/O reference.
126 */
127typedef struct _Eio_File Eio_File;
128
129/**
130 * @typedef Eio_Progress
131 * Progress information on a specific operation.
132 */
133typedef struct _Eio_Progress Eio_Progress;
134
135typedef Eina_Bool (*Eio_Filter_Cb)(void *data, Eio_File *handler, const char *file);
136typedef void (*Eio_Main_Cb)(void *data, Eio_File *handler, const char *file);
137
138typedef Eina_Bool (*Eio_Filter_Direct_Cb)(void *data, Eio_File *handler, const Eina_File_Direct_Info *info);
139typedef Eina_Bool (*Eio_Filter_Dir_Cb)(void *data, Eio_File *handler, Eina_File_Direct_Info *info);
140typedef void (*Eio_Main_Direct_Cb)(void *data, Eio_File *handler, const Eina_File_Direct_Info *info);
141
142typedef void (*Eio_Stat_Cb)(void *data, Eio_File *handler, const Eina_Stat *stat);
143typedef void (*Eio_Progress_Cb)(void *data, Eio_File *handler, const Eio_Progress *info);
144
145typedef void (*Eio_Eet_Open_Cb)(void *data, Eio_File *handler, Eet_File *file);
146typedef void (*Eio_Open_Cb)(void *data, Eio_File *handler, Eina_File *file);
147typedef Eina_Bool (*Eio_Filter_Map_Cb)(void *data, Eio_File *handler, void *map, size_t length);
148typedef void (*Eio_Map_Cb)(void *data, Eio_File *handler, void *map, size_t length);
149
150typedef void (*Eio_Done_Data_Cb)(void *data, Eio_File *handler, const char *read_data, unsigned int size);
151typedef void (*Eio_Done_String_Cb)(void *data, Eio_File *handler, const char *xattr_string);
152typedef void (*Eio_Done_Double_Cb)(void *data, Eio_File *handler, double xattr_double);
153typedef void (*Eio_Done_Int_Cb)(void *data, Eio_File *handler, int i);
154
155typedef void (*Eio_Done_ERead_Cb)(void *data, Eio_File *handler, void *decoded);
156typedef void (*Eio_Done_Read_Cb)(void *data, Eio_File *handler, void *read_data, unsigned int size);
157typedef void (*Eio_Done_Cb)(void *data, Eio_File *handler);
158typedef void (*Eio_Error_Cb)(void *data, Eio_File *handler, int error);
159typedef void (*Eio_Eet_Error_Cb)(void *data, Eio_File *handler, Eet_Error err);
160
161/**
162 * @struct _Eio_Progress
163 * @brief Represents the current progress of the operation.
164 */
165struct _Eio_Progress
166{
167 Eio_File_Op op; /**< I/O type */
168
169 long long current; /**< Current step in the I/O operation */
170 long long max; /**< Number of total steps to complete this I/O */
171 float percent; /**< Percent done for the I/O operation */
172
173 const char *source; /**< source of the I/O operation */
174 const char *dest; /**< target of the I/O operation */
175};
176
177/**
178 * @brief List contents of a directory without locking your app.
179 * @param dir The directory to list.
180 * @param filter_cb Callback used to decide if the file will be passed to main_cb
181 * @param main_cb Callback called for each listed file if it was not filtered.
182 * @param done_cb Callback called when the ls operation is done.
183 * @param error_cb Callback called when either the directory could not be opened or the operation has been canceled.
184 * @param data Unmodified user data passed to callbacks
185 * @return A reference to the I/O operation.
186 *
187 * This function is responsible for listing the content of a directory without blocking your application.
188 * It's equivalent to the "ls" shell command. Every file will be passed to the
189 * filter_cb, so it's your job to decide if you want to pass the file to the
190 * main_cb or not. Return EINA_TRUE to pass it to the main_cb or EINA_FALSE to
191 * ignore it.
192 */
193EAPI Eio_File *eio_file_ls(const char *dir,
194 Eio_Filter_Cb filter_cb,
195 Eio_Main_Cb main_cb,
196 Eio_Done_Cb done_cb,
197 Eio_Error_Cb error_cb,
198 const void *data);
199
200/**
201 * @brief List contents of a directory without locking your app.
202 * @param dir The directory to list.
203 * @param filter_cb Callback used to decide if the file will be passed to main_cb
204 * @param main_cb Callback called from the main loop for each accepted file (not filtered).
205 * @param done_cb Callback called from the main loop after the contents of the directory has been listed.
206 * @param error_cb Callback called from the main loop when either the directory could not be opened or the operation has been canceled.
207 * @param data Unmodified user data passed to callbacks
208 * @return A reference to the I/O operation.
209 *
210 * eio_file_direct_ls runs eina_file_direct_ls in a separate thread using
211 * ecore_thread_feedback_run. This prevents any blocking in your apps.
212 * Every file will be passed to the filter_cb, so it's your job to decide if you
213 * want to pass the file to the main_cb or not. Return EINA_TRUE to pass it to
214 * the main_cb or EINA_FALSE to ignore it.
215 */
216EAPI Eio_File *eio_file_direct_ls(const char *dir,
217 Eio_Filter_Direct_Cb filter_cb,
218 Eio_Main_Direct_Cb main_cb,
219 Eio_Done_Cb done_cb,
220 Eio_Error_Cb error_cb,
221 const void *data);
222
223/**
224 * @brief List content of a directory without locking your app.
225 * @param dir The directory to list.
226 * @param filter_cb Callback used to decide if the file will be passed to main_cb
227 * @param main_cb Callback called from the main loop for each accepted file (not filtered).
228 * @param done_cb Callback called from the main loop after the contents of the directory has been listed.
229 * @param error_cb Callback called from the main loop when either the directory could not be opened or the operation has been canceled.
230 * @param data Unmodified user data passed to callbacks
231 * @return A reference to the I/O operation.
232 *
233 * Every file will be passed to the filter_cb, so it's your job to decide if you
234 * want to pass the file to the main_cb or not. Return EINA_TRUE to pass it to
235 * the main_cb or EINA_FALSE to ignore it.
236 *
237 */
238EAPI Eio_File *eio_file_stat_ls(const char *dir,
239 Eio_Filter_Direct_Cb filter_cb,
240 Eio_Main_Direct_Cb main_cb,
241 Eio_Done_Cb done_cb,
242 Eio_Error_Cb error_cb,
243 const void *data);
244
245/**
246 * @brief List the content of a directory and all it's sub-content asynchronously
247 * @param dir The directory to list.
248 * @param filter_cb Callback used to decide if the file will be passed to main_cb
249 * @param main_cb Callback called from the main loop for each accepted file (not filtered).
250 * @param done_cb Callback called from the main loop after the contents of the directory has been listed.
251 * @param error_cb Callback called from the main loop when either the directory could not be opened or the operation has been canceled.
252 * @param data Unmodified user data passed to callbacks
253 * @return A reference to the I/O operation.
254 *
255 * eio_dir_stat_ls() runs eina_file_stat_ls() recursively in a separate thread using
256 * ecore_thread_feedback_run. This prevents any blocking in your apps.
257 * Every file will be passed to the
258 * filter_cb, so it's your job to decide if you want to pass the file to the
259 * main_cb or not. Return EINA_TRUE to pass it to the main_cb or EINA_FALSE to
260 * ignore it.
261 */
262EAPI Eio_File *eio_dir_stat_ls(const char *dir,
263 Eio_Filter_Direct_Cb filter_cb,
264 Eio_Main_Direct_Cb main_cb,
265 Eio_Done_Cb done_cb,
266 Eio_Error_Cb error_cb,
267 const void *data);
268
269/**
270 * @brief List the content of a directory and all it's sub-content asynchronously
271 * @param dir The directory to list.
272 * @param filter_cb Callback used to decide if the file will be passed to main_cb
273 * @param main_cb Callback called from the main loop for each accepted file (not filtered).
274 * @param done_cb Callback called from the main loop after the contents of the directory has been listed.
275 * @param error_cb Callback called from the main loop when either the directory could not be opened or the operation has been canceled.
276 * @param data Unmodified user data passed to callbacks
277 * @return A reference to the I/O operation.
278 *
279 * eio_dir_direct_ls() runs eina_file_direct_ls() recursively in a separate thread using
280 * ecore_thread_feedback_run. This prevents any blocking in your apps.
281 * Every file will be passed to the filter_cb, so it's your job to decide if you
282 * want to pass the file to the main_cb or not. Return EINA_TRUE to pass it to
283 * the main_cb or EINA_FALSE to ignore it.
284 */
285EAPI Eio_File *eio_dir_direct_ls(const char *dir,
286 Eio_Filter_Dir_Cb filter_cb,
287 Eio_Main_Direct_Cb main_cb,
288 Eio_Done_Cb done_cb,
289 Eio_Error_Cb error_cb,
290 const void *data);
291
292/**
293 * @brief Stat a file/directory.
294 * @param path The path to stat.
295 * @param done_cb Callback called from the main loop when stat was successfully called.
296 * @param error_cb Callback called from the main loop when stat failed or has been canceled.
297 * @param data Unmodified user data passed to callbacks
298 * @return A reference to the I/O operation.
299 *
300 * eio_file_direct_stat calls stat in another thread. This prevents any blocking in your apps.
301 */
302EAPI Eio_File *eio_file_direct_stat(const char *path,
303 Eio_Stat_Cb done_cb,
304 Eio_Error_Cb error_cb,
305 const void *data);
306
307/**
308 * @brief Change right of a path.
309 * @param path The directory path to change access right.
310 * @param mode The permission to set, follow (mode & ~umask & 0777).
311 * @param done_cb Callback called when the operation is completed.
312 * @param error_cb Callback called from if something goes wrong.
313 * @param data Unmodified user data passed to callbacks.
314 * @return A reference to the I/O operation.
315 *
316 * Set a new permission of a path changing it to the mode passed as argument.
317 * It's equivalent to the chmod command.
318 */
319EAPI Eio_File *eio_file_chmod(const char *path,
320 mode_t mode,
321 Eio_Done_Cb done_cb,
322 Eio_Error_Cb error_cb,
323 const void *data);
324
325/**
326 * @brief Change owner of a path.
327 * @param path The directory path to change owner.
328 * @param user The new user to set (can be NULL).
329 * @param group The new group to set (can be NULL).
330 * @param done_cb Callback called when the operation is completed.
331 * @param error_cb Callback called from if something goes wrong.
332 * @param data Unmodified user data passed to callbacks
333 * @return A reference to the I/O operation.
334 *
335 * This function will change the owner of a path, setting it to the user and
336 * group passed as argument. It's equivalent to the chown shell command.
337 */
338EAPI Eio_File *eio_file_chown(const char *path,
339 const char *user,
340 const char *group,
341 Eio_Done_Cb done_cb,
342 Eio_Error_Cb error_cb,
343 const void *data);
344
345/**
346 * @brief Unlink a file/directory.
347 * @param path The path to unlink.
348 * @param done_cb Callback called when the operation is completed.
349 * @param error_cb Callback called from if something goes wrong.
350 * @param data Unmodified user data passed to callbacks.
351 * @return A reference to the I/O operation.
352 *
353 * This function will erase a file.
354 */
355EAPI Eio_File *eio_file_unlink(const char *path,
356 Eio_Done_Cb done_cb,
357 Eio_Error_Cb error_cb,
358 const void *data);
359
360/**
361 * @brief Create a new directory.
362 * @param path The directory path to create.
363 * @param mode The permission to set, follow (mode & ~umask & 0777).
364 * @param done_cb Callback called when the operation is completed.
365 * @param error_cb Callback called from if something goes wrong.
366 * @param data Unmodified user data passed to callbacks
367 * @return A reference to the I/O operation.
368 *
369 * Creates a new directory using the mode provided.
370 */
371EAPI Eio_File *eio_file_mkdir(const char *path,
372 mode_t mode,
373 Eio_Done_Cb done_cb,
374 Eio_Error_Cb error_cb,
375 const void *data);
376
377/**
378 * @brief Move a file asynchronously
379 * @param source Should be the name of the file to move the data from.
380 * @param dest Should be the name of the file to move the data to.
381 * @param progress_cb Callback called to know the progress of the move.
382 * @param done_cb Callback called when the move is done.
383 * @param error_cb Callback called when something goes wrong.
384 * @param data Unmodified user data passed to callbacks
385 *
386 * This function will copy a file from source to dest. It will try to use splice
387 * if possible, if not it will fallback to mmap/write. It will try to preserve
388 * access right, but not user/group identification.
389 */
390EAPI Eio_File *eio_file_move(const char *source,
391 const char *dest,
392 Eio_Progress_Cb progress_cb,
393 Eio_Done_Cb done_cb,
394 Eio_Error_Cb error_cb,
395 const void *data);
396
397/**
398 * @brief Copy a file asynchronously
399 * @param source Should be the name of the file to copy the data from.
400 * @param dest Should be the name of the file to copy the data to.
401 * @param progress_cb Callback called to know the progress of the copy.
402 * @param done_cb Callback called when the copy is done.
403 * @param error_cb Callback called when something goes wrong.
404 * @param data Unmodified user data passed to callbacks
405 *
406 * This function will copy a file from source to dest. It will try to use splice
407 * if possible, if not it will fallback to mmap/write. It will try to preserve
408 * access right, but not user/group identification.
409 */
410EAPI Eio_File *eio_file_copy(const char *source,
411 const char *dest,
412 Eio_Progress_Cb progress_cb,
413 Eio_Done_Cb done_cb,
414 Eio_Error_Cb error_cb,
415 const void *data);
416
417/**
418 * @brief Move a directory and it's content asynchronously
419 * @param source Should be the name of the directory to copy the data from.
420 * @param dest Should be the name of the directory to copy the data to.
421 * @param filter_cb Possible to deny the move of some files/directories.
422 * @param progress_cb Callback called to know the progress of the copy.
423 * @param done_cb Callback called when the copy is done.
424 * @param error_cb Callback called when something goes wrong.
425 * @param data Unmodified user data passed to callbacks
426 *
427 * This function will move a directory and all it's content from source to dest.
428 * It will try first to rename the directory, if not it will try to use splice
429 * if possible, if not it will fallback to mmap/write.
430 * It will try to preserve access right, but not user/group identity.
431 * Every file will be passed to the filter_cb, so it's your job to decide if you
432 * want to pass the file to the main_cb or not. Return EINA_TRUE to pass it to
433 * the main_cb or EINA_FALSE to ignore it.
434 *
435 * @note if a rename occur, the filter callback will not be called.
436 */
437EAPI Eio_File *eio_dir_move(const char *source,
438 const char *dest,
439 Eio_Filter_Direct_Cb filter_cb,
440 Eio_Progress_Cb progress_cb,
441 Eio_Done_Cb done_cb,
442 Eio_Error_Cb error_cb,
443 const void *data);
444
445/**
446 * @brief Copy a directory and it's content asynchronously
447 * @param source Should be the name of the directory to copy the data from.
448 * @param dest Should be the name of the directory to copy the data to.
449 * @param filter_cb Possible to deny the move of some files/directories.
450 * @param progress_cb Callback called to know the progress of the copy.
451 * @param done_cb Callback called when the copy is done.
452 * @param error_cb Callback called when something goes wrong.
453 * @param data Unmodified user data passed to callbacks
454 *
455 * This function will copy a directory and all it's content from source to dest.
456 * It will try to use splice if possible, if not it will fallback to mmap/write.
457 * It will try to preserve access right, but not user/group identity.
458 * Every file will be passed to the filter_cb, so it's your job to decide if you
459 * want to pass the file to the main_cb or not. Return EINA_TRUE to pass it to
460 * the main_cb or EINA_FALSE to ignore it.
461 */
462EAPI Eio_File *eio_dir_copy(const char *source,
463 const char *dest,
464 Eio_Filter_Direct_Cb filter_cb,
465 Eio_Progress_Cb progress_cb,
466 Eio_Done_Cb done_cb,
467 Eio_Error_Cb error_cb,
468 const void *data);
469
470/**
471 * @brief Remove a directory and it's content asynchronously
472 * @param path Should be the name of the directory to destroy.
473 * @param filter_cb Possible to deny the move of some files/directories.
474 * @param progress_cb Callback called to know the progress of the copy.
475 * @param done_cb Callback called when the copy is done.
476 * @param error_cb Callback called when something goes wrong.
477 * @param data Unmodified user data passed to callbacks
478 *
479 * This function will remove a directory and all it's content.
480 * Every file will be passed to the filter_cb, so it's your job to decide if you
481 * want to pass the file to the main_cb or not. Return EINA_TRUE to pass it to
482 * the main_cb or EINA_FALSE to ignore it.
483 */
484EAPI Eio_File *eio_dir_unlink(const char *path,
485 Eio_Filter_Direct_Cb filter_cb,
486 Eio_Progress_Cb progress_cb,
487 Eio_Done_Cb done_cb,
488 Eio_Error_Cb error_cb,
489 const void *data);
490/**
491 * @}
492 */
493
494
495/**
496 * @defgroup Eio_Xattr Eio manipulation of eXtended attribute.
497 *
498 * @brief A set of function to manipulate data associated with a specific file
499 *
500 * The functions provided by this API are responsible to manage Extended
501 * attribute files. Like file authors, character encoding, checksum, etc.
502 * @{
503 */
504
505/**
506 * @brief Assynchronously list all eXtended attribute
507 * @param path The path to get the eXtended attribute from.
508 * @param filter_cb Callback called in the thread to validate the eXtended attribute.
509 * @param main_cb Callback called in the main loop for each accepted eXtended attribute.
510 * @param done_cb Callback called in the main loop when the all the eXtended attribute have been listed.
511 * @param error_cb Callback called in the main loop when something goes wrong during the listing of the eXtended attribute.
512 * @param data Unmodified user data passed to callbacks
513 * @return A reference to the I/O operation.
514 */
515EAPI Eio_File *eio_file_xattr(const char *path,
516 Eio_Filter_Cb filter_cb,
517 Eio_Main_Cb main_cb,
518 Eio_Done_Cb done_cb,
519 Eio_Error_Cb error_cb,
520 const void *data);
521
522/**
523 * @brief Define an extented attribute on a file/directory.
524 * @param path The path to set the attribute on.
525 * @param attribute The name of the attribute to define.
526 * @param xattr_int The value to link the attribute with.
527 * @param flags Wether to insert, replace or create the attribute.
528 * @param done_cb The callback called from the main loop when setxattr succeeded.
529 * @param error_cb The callback called from the main loop when setxattr failed.
530 * @param data Unmodified user data passed to callbacks
531 * @return A reference to the I/O operation.
532 *
533 * eio_file_xattr_int_set calls eina_xattr_int_set from another thread. This prevents blocking in your apps. If
534 * the writing succeeded, the done_cb will be called even if a cancel was requested, but came to late.
535 */
536EAPI Eio_File *eio_file_xattr_int_set(const char *path,
537 const char *attribute,
538 int xattr_int,
539 Eina_Xattr_Flags flags,
540 Eio_Done_Cb done_cb,
541 Eio_Error_Cb error_cb,
542 const void *data);
543
544/**
545 * @brief Define an extented attribute on a file/directory.
546 * @param path The path to set the attribute on.
547 * @param attribute The name of the attribute to define.
548 * @param xattr_double The value to link the attribute with.
549 * @param flags Wether to insert, replace or create the attribute.
550 * @param done_cb The callback called from the main loop when setxattr succeeded.
551 * @param error_cb The callback called from the main loop when setxattr failed.
552 * @param data Unmodified user data passed to callbacks
553 * @return A reference to the I/O operation.
554 *
555 * eio_file_xattr_double_set calls eina_xattr_double_set from another thread. This prevents blocking in your apps. If
556 * the writing succeeded, the done_cb will be called even if a cancel was requested, but came to late.
557 */
558EAPI Eio_File *eio_file_xattr_double_set(const char *path,
559 const char *attribute,
560 double xattr_double,
561 Eina_Xattr_Flags flags,
562 Eio_Done_Cb done_cb,
563 Eio_Error_Cb error_cb,
564 const void *data);
565/**
566 * @brief Define a string extented attribute on a file/directory.
567 * @param path The path to set the attribute on.
568 * @param attribute The name of the attribute to define.
569 * @param xattr_string The string to link the attribute with.
570 * @param flags Wether to insert, replace or create the attribute.
571 * @param done_cb The callback called from the main loop when setxattr succeeded.
572 * @param error_cb The callback called from the main loop when setxattr failed.
573 * @param data Unmodified user data passed to callbacks
574 * @return A reference to the I/O operation.
575 *
576 * eio_file_xattr_string_set calls eina_xattr_string_set from another thread. This prevents blocking in your apps. If
577 * the writing succeeded, the done_cb will be called even if a cancel was requested, but came to late.
578 */
579EAPI Eio_File *eio_file_xattr_string_set(const char *path,
580 const char *attribute,
581 const char *xattr_string,
582 Eina_Xattr_Flags flags,
583 Eio_Done_Cb done_cb,
584 Eio_Error_Cb error_cb,
585 const void *data);
586/**
587 * @brief Define an extented attribute on a file/directory.
588 * @param path The path to set the attribute on.
589 * @param attribute The name of the attribute to define.
590 * @param xattr_data The data to link the attribute with.
591 * @param xattr_size The size of the data to set.
592 * @param flags Wether to insert, replace or create the attribute.
593 * @param done_cb The callback called from the main loop when setxattr succeeded.
594 * @param error_cb The callback called from the main loop when setxattr failed.
595 * @param data Unmodified user data passed to callbacks
596 * @return A reference to the I/O operation.
597 *
598 * eio_file_xattr_set calls setxattr from another thread. This prevents blocking in your apps. If
599 * the writing succeeded, the done_cb will be called even if a cancel was requested, but came to late.
600 */
601EAPI Eio_File *eio_file_xattr_set(const char *path,
602 const char *attribute,
603 const char *xattr_data,
604 unsigned int xattr_size,
605 Eina_Xattr_Flags flags,
606 Eio_Done_Cb done_cb,
607 Eio_Error_Cb error_cb,
608 const void *data);
609
610/**
611 * @brief Retrieve the extended attribute of a file/directory.
612 * @param path The path to retrieve the extended attribute from.
613 * @param attribute The name of the attribute to retrieve.
614 * @param done_cb Callback called from the main loop when getxattr succeeded.
615 * @param error_cb Callback called from the main loop when getxattr failed or has been canceled.
616 * @param data Unmodified user data passed to callbacks
617 * @return A reference to the I/O operation.
618 *
619 * eio_file_xattr_get calls getxattr from another thread. This prevents blocking in your apps.
620 */
621EAPI Eio_File *eio_file_xattr_get(const char *path,
622 const char *attribute,
623 Eio_Done_Data_Cb done_cb,
624 Eio_Error_Cb error_cb,
625 const void *data);
626/**
627 * @brief Retrieve a extended attribute of a file/directory.
628 * @param path The path to retrieve the extended attribute from.
629 * @param attribute The name of the attribute to retrieve.
630 * @param done_cb Callback called from the main loop when getxattr succeeded.
631 * @param error_cb Callback called from the main loop when getxattr failed or has been canceled.
632 * @param data Unmodified user data passed to callbacks
633 * @return A reference to the I/O operation.
634 *
635 * eio_file_xattr_int_get calls eina_xattr_int_get from another thread. This prevents blocking in your apps.
636 */
637EAPI Eio_File *eio_file_xattr_int_get(const char *path,
638 const char *attribute,
639 Eio_Done_Int_Cb done_cb,
640 Eio_Error_Cb error_cb,
641 const void *data);
642/**
643 * @brief Retrieve a extended attribute of a file/directory.
644 * @param path The path to retrieve the extended attribute from.
645 * @param attribute The name of the attribute to retrieve.
646 * @param done_cb Callback called from the main loop when getxattr succeeded.
647 * @param error_cb Callback called from the main loop when getxattr failed or has been canceled.
648 * @param data Unmodified user data passed to callbacks
649 * @return A reference to the I/O operation.
650 *
651 * eio_file_xattr_double_get calls eina_xattr_double_get from another thread. This prevents blocking in your apps.
652 */
653EAPI Eio_File *eio_file_xattr_double_get(const char *path,
654 const char *attribute,
655 Eio_Done_Double_Cb done_cb,
656 Eio_Error_Cb error_cb,
657 const void *data);
658/**
659 * @brief Retrieve a string extended attribute of a file/directory.
660 * @param path The path to retrieve the extended attribute from.
661 * @param attribute The name of the attribute to retrieve.
662 * @param done_cb Callback called from the main loop when getxattr succeeded.
663 * @param error_cb Callback called from the main loop when getxattr failed or has been canceled.
664 * @param data Unmodified user data passed to callbacks
665 * @return A reference to the I/O operation.
666 *
667 * eio_file_xattr_string_get calls eina_xattr_string_get from another thread. This prevents blocking in your apps.
668 */
669EAPI Eio_File *eio_file_xattr_string_get(const char *path,
670 const char *attribute,
671 Eio_Done_String_Cb done_cb,
672 Eio_Error_Cb error_cb,
673 const void *data);
674
675/**
676 * @}
677 */
678
679/**
680 * @defgroup Eio_Helper Eio Reference helper API
681 *
682 * @brief This are helper provided around core Eio API.
683 *
684 * This set of functions do provide helper to work around data
685 * provided by Eio without the need to look at system header.
686 *
687 * @{
688 */
689
690
691/**
692 * @brief Initialize eio and all it's required submodule.
693 * @return the current number of eio users.
694 */
695EAPI int eio_init(void);
696
697/**
698 * @brief Shutdown eio and all it's submodule if possible.
699 * @return the number of pending users of eio.
700 */
701EAPI int eio_shutdown(void);
702
703/**
704 * @brief Return the container during EIO operation
705 * @param ls The asynchronous I/O operation to retrieve container from.
706 * @return NULL if not available, a DIRP if it is.
707 *
708 * This is only available and make sense in the thread callback, not in
709 * the mainloop.
710 */
711EAPI void *eio_file_container_get(Eio_File *ls);
712
713/**
714 * @brief Cancel any Eio_File.
715 * @param ls The asynchronous I/O operation to cancel.
716 * @return EINA_FALSE if the destruction is delayed, EINA_TRUE if it's done.
717 *
718 * This will cancel any kind of I/O operation and cleanup the mess. This means
719 * that it could take time to cancel an I/O.
720 */
721EAPI Eina_Bool eio_file_cancel(Eio_File *ls);
722
723/**
724 * @brief Check if an Eio_File operation has been cancelled.
725 * @param ls The asynchronous I/O operation to check.
726 * @return EINA_TRUE if it was canceled, EINA_FALSE other wise.
727 *
728 * In case of an error it also return EINA_TRUE.
729 */
730EAPI Eina_Bool eio_file_check(Eio_File *ls);
731
732/**
733 * @brief Associate data with the current filtered file.
734 * @param ls The Eio_File ls request currently calling the filter callback.
735 * @param key The key to associate data to.
736 * @param data The data to associate the data to.
737 * @param free_cb Optionally a function to call to free the associated data,
738 * @p data is passed as the callback data parameter. If no @free_cb is provided
739 * the user @p data remains untouched.
740 * @return EINA_TRUE if insertion was fine.
741 *
742 * This function can only be safely called from within the filter callback.
743 * If you don't need to copy the key around you can use @ref eio_file_associate_direct_add
744 */
745EAPI Eina_Bool eio_file_associate_add(Eio_File *ls,
746 const char *key,
747 const void *data, Eina_Free_Cb free_cb);
748
749/**
750 * @brief Associate data with the current filtered file.
751 * @param ls The Eio_File ls request currently calling the filter callback.
752 * @param key The key to associate data to (will not be copied, and the pointer will not be used as long as the file is not notified).
753 * @param data The data to associate the data to.
754 * @param free_cb The function to call to free the associated data, @p free will be called if not specified.
755 * @return EINA_TRUE if insertion was fine.
756 *
757 * This function can only be safely called from within the filter callback.
758 * If you need eio to make a proper copy of the @p key to be safe use
759 * @ref eio_file_associate_add instead.
760 */
761EAPI Eina_Bool eio_file_associate_direct_add(Eio_File *ls,
762 const char *key,
763 const void *data, Eina_Free_Cb free_cb);
764
765/**
766 * @brief Get the data associated during the filter callback inside the main loop
767 * @param ls The Eio_File ls request currently calling the notify callback.
768 * @param key The key pointing to the data to retrieve.
769 * @return the data associated with the key or @p NULL if not found.
770 */
771EAPI void *eio_file_associate_find(Eio_File *ls, const char *key);
772
773/**
774 * @brief get access time from a Eina_Stat
775 * @param stat the structure to get the atime from
776 * @return the last accessed time
777 *
778 * This take care of doing type conversion to match rest of EFL time API.
779 * @note some filesystem don't update that information.
780 */
781static inline double eio_file_atime(const Eina_Stat *stat);
782
783/**
784 * @brief get modification time from a Eina_Stat
785 * @param stat the structure to get the mtime from
786 * @return the last modification time
787 *
788 * This take care of doing type conversion to match rest of EFL time API.
789 */
790static inline double eio_file_mtime(const Eina_Stat *stat);
791
792/**
793 * @brief get the size of the file described in Eina_Stat
794 * @param stat the structure to get the size from
795 * @return the size of the file
796 */
797static inline long long eio_file_size(const Eina_Stat *stat);
798
799/**
800 * @brief tell if the stated path was a directory or not.
801 * @param stat the structure to get the size from
802 * @return EINA_TRUE, if it was.
803 */
804static inline Eina_Bool eio_file_is_dir(const Eina_Stat *stat);
805
806/**
807 * @brief tell if the stated path was a link or not.
808 * @param stat the structure to get the size from
809 * @return EINA_TRUE, if it was.
810 */
811static inline Eina_Bool eio_file_is_lnk(const Eina_Stat *stat);
812
813/**
814 * @}
815 */
816
817/**
818 *
819 */
820
821/**
822 * @defgroup Eio_Map Manipulate an Eina_File asynchronously
823 *
824 * @brief This function help manipulating file asynchronously.
825 *
826 * This set of function work on top of Eina_File and Ecore_Thread to
827 * do basic operations in a file, like openning, closing and mapping a file to
828 * memory.
829 * @{
830 */
831
832/**
833 * @brief Assynchronously open a file.
834 * @param name The file to open.
835 * @param shared If it's a shared memory file.
836 * @param open_cb Callback called in the main loop when the file has been successfully opened.
837 * @param error_cb Callback called in the main loop when the file couldn't be opened.
838 * @param data Unmodified user data passed to callbacks
839 * @return Pointer to the file if successfull or NULL otherwise.
840 *
841 */
842EAPI Eio_File *eio_file_open(const char *name, Eina_Bool shared,
843 Eio_Open_Cb open_cb,
844 Eio_Error_Cb error_cb,
845 const void *data);
846
847/**
848 * @brief Assynchronously close a file.
849 * @param f The file to close.
850 * @param done_cb Callback called in the main loop when the file has been successfully closed.
851 * @param error_cb Callback called in the main loop when the file couldn't be closed.
852 * @param data Unmodified user data passed to callbacks
853 * @return Pointer to the file if successfull or NULL otherwise.
854 */
855EAPI Eio_File *eio_file_close(Eina_File *f,
856 Eio_Done_Cb done_cb,
857 Eio_Error_Cb error_cb,
858 const void *data);
859
860/**
861 * @brief Assynchronously map a file in memory.
862 * @param f The file to map.
863 * @param rule The rule to apply to the map.
864 * @param filter_cb Callback called in the thread to validate the content of the map.
865 * @param map_cb Callback called in the main loop when the file has been successfully mapped.
866 * @param error_cb Callback called in the main loop when the file can't be mapped.
867 * @param data Unmodified user data passed to callbacks
868 * @return Pointer to the file if successfull or NULL otherwise.
869 *
870 * The container of the Eio_File is the Eina_File.
871 */
872EAPI Eio_File *eio_file_map_all(Eina_File *f,
873 Eina_File_Populate rule,
874 Eio_Filter_Map_Cb filter_cb,
875 Eio_Map_Cb map_cb,
876 Eio_Error_Cb error_cb,
877 const void *data);
878
879/**
880 * @brief Assynchronously map a part of a file in memory.
881 * @param f The file to map.
882 * @param rule The rule to apply to the map.
883 * @param offset The offset inside the file
884 * @param length The length of the memory to map
885 * @param filter_cb Callback called in the thread to validate the content of the map.
886 * @param map_cb Callback called in the main loop when the file has been successfully mapped.
887 * @param error_cb Callback called in the main loop when the file can't be mapped.
888 * @param data Unmodified user data passed to callbacks
889 * @return Pointer to the file if successfull or NULL otherwise.
890 *
891 * The container of the Eio_File is the Eina_File.
892 */
893EAPI Eio_File *eio_file_map_new(Eina_File *f,
894 Eina_File_Populate rule,
895 unsigned long int offset,
896 unsigned long int length,
897 Eio_Filter_Map_Cb filter_cb,
898 Eio_Map_Cb map_cb,
899 Eio_Error_Cb error_cb,
900 const void *data);
901
902/**
903 * @}
904 */
905
906/**
907 * @defgroup Eio_Eet Eio asynchronous API for Eet file.
908 *
909 * @brief This set of functions help in the asynchronous use of Eet
910 *
911 * @{
912 */
913
914/**
915 * @brief Open an eet file on disk, and returns a handle to it asynchronously.
916 * @param filename The file path to the eet file. eg: @c "/tmp/file.eet".
917 * @param mode The mode for opening. Either EET_FILE_MODE_READ,
918 * EET_FILE_MODE_WRITE or EET_FILE_MODE_READ_WRITE.
919 * @param eet_cb The callback to call when the file has been successfully opened.
920 * @param error_cb Callback called in the main loop when the file can't be opened.
921 * @param data Unmodified user data passed to callbacks
922 * @return NULL in case of a failure.
923 *
924 * This function calls eet_open() from another thread using Ecore_Thread.
925 */
926EAPI Eio_File *eio_eet_open(const char *filename,
927 Eet_File_Mode mode,
928 Eio_Eet_Open_Cb eet_cb,
929 Eio_Error_Cb error_cb,
930 const void *data);
931/**
932 * @brief Close an eet file handle and flush pending writes asynchronously.
933 * @param ef A valid eet file handle.
934 * @param done_cb Callback called from the main loop when the file has been closed.
935 * @param error_cb Callback called in the main loop when the file can't be closed.
936 * @param data Unmodified user data passed to callbacks
937 * @return NULL in case of a failure.
938 *
939 * This function will call eet_close() from another thread by
940 * using Ecore_Thread. You should assume that the Eet_File is dead after this
941 * function is called.
942 */
943EAPI Eio_File *eio_eet_close(Eet_File *ef,
944 Eio_Done_Cb done_cb,
945 Eio_Eet_Error_Cb error_cb,
946 const void *data);
947
948/**
949 * @brief Sync content of an eet file handle, flushing pending writes asynchronously.
950 * @param ef A valid eet file handle.
951 * @param done_cb Callback called from the main loop when the file has been synced.
952 * @param error_cb Callback called in the main loop when the file can't be synced.
953 * @param data Unmodified user data passed to callbacks
954 * @return NULL in case of a failure.
955 *
956 * This function will call eet_flush() from another thread. As long as the done_cb or
957 * error_cb haven't be called, you must keep @p ef open.
958 */
959EAPI Eio_File *eio_eet_sync(Eet_File *ef,
960 Eio_Done_Cb done_cb,
961 Eio_Eet_Error_Cb error_cb,
962 const void *data);
963
964/**
965 * @brief Write a data structure from memory and store in an eet file
966 * using a cipher asynchronously.
967 * @param ef The eet file handle to write to.
968 * @param edd The data descriptor to use when encoding.
969 * @param name The key to store the data under in the eet file.
970 * @param cipher_key The key to use as cipher.
971 * @param write_data A pointer to the data structure to save and encode.
972 * @param compress Compression flags for storage.
973 * @param done_cb Callback called from the main loop when the data has been put in the Eet_File.
974 * @param error_cb Callback called in the main loop when the file can't be written.
975 * @param user_data Private data given to each callback.
976 * @return NULL in case of a failure.
977 */
978EAPI Eio_File *eio_eet_data_write_cipher(Eet_File *ef,
979 Eet_Data_Descriptor *edd,
980 const char *name,
981 const char *cipher_key,
982 void *write_data,
983 int compress,
984 Eio_Done_Int_Cb done_cb,
985 Eio_Error_Cb error_cb,
986 const void *user_data);
987
988/**
989 * @brief Read a data structure from an eet file and decodes it using a cipher asynchronously.
990 * @param ef The eet file handle to read from.
991 * @param edd The data descriptor handle to use when decoding.
992 * @param name The key the data is stored under in the eet file.
993 * @param cipher_key The key to use as cipher.
994 * @param done_cb Callback called from the main loop when the data has been read and decoded.
995 * @param error_cb Callback called in the main loop when the data can't be read.
996 * @param data Unmodified user data passed to callbacks
997 * @return NULL in case of a failure.
998 */
999EAPI Eio_File *eio_eet_data_read_cipher(Eet_File *ef,
1000 Eet_Data_Descriptor *edd,
1001 const char *name,
1002 const char *cipher_key,
1003 Eio_Done_ERead_Cb done_cb,
1004 Eio_Error_Cb error_cb,
1005 const void *data);
1006
1007/**
1008 * @brief Write image data to the named key in an eet file asynchronously.
1009 * @param ef A valid eet file handle opened for writing.
1010 * @param name Name of the entry. eg: "/base/file_i_want".
1011 * @param cipher_key The key to use as cipher.
1012 * @param write_data A pointer to the image pixel data.
1013 * @param w The width of the image in pixels.
1014 * @param h The height of the image in pixels.
1015 * @param alpha The alpha channel flag.
1016 * @param compress The compression amount.
1017 * @param quality The quality encoding amount.
1018 * @param lossy The lossiness flag.
1019 * @param done_cb Callback called from the main loop when the data has been put in the Eet_File.
1020 * @param error_cb Callback called in the main loop when the file can't be written.
1021 * @param user_data Private data given to each callback.
1022 * @return NULL in case of a failure.
1023 */
1024EAPI Eio_File *eio_eet_data_image_write_cipher(Eet_File *ef,
1025 const char *name,
1026 const char *cipher_key,
1027 void *write_data,
1028 unsigned int w,
1029 unsigned int h,
1030 int alpha,
1031 int compress,
1032 int quality,
1033 int lossy,
1034 Eio_Done_Int_Cb done_cb,
1035 Eio_Error_Cb error_cb,
1036 const void *user_data);
1037
1038/**
1039 * @brief Read a specified entry from an eet file and return data
1040 * @param ef A valid eet file handle opened for reading.
1041 * @param name Name of the entry. eg: "/base/file_i_want".
1042 * @param done_cb Callback called from the main loop when the data has been read.
1043 * @param error_cb Callback called in the main loop when the data can't be read.
1044 * @param data Unmodified user data passed to callbacks
1045 * @return NULL in case of a failure.
1046 */
1047EAPI Eio_File *eio_eet_read_direct(Eet_File *ef,
1048 const char *name,
1049 Eio_Done_Data_Cb done_cb,
1050 Eio_Error_Cb error_cb,
1051 const void *data);
1052
1053/**
1054 * @brief Read a specified entry from an eet file and return data
1055 * @param ef A valid eet file handle opened for reading.
1056 * @param name Name of the entry. eg: "/base/file_i_want".
1057 * @param cipher_key The key to use as cipher.
1058 * @param done_cb Callback called from the main loop when the data has been read.
1059 * @param error_cb Callback called in the main loop when the data can't be read.
1060 * @param data Unmodified user data passed to callbacks
1061 * @return NULL in case of a failure.
1062 */
1063EAPI Eio_File *eio_eet_read_cipher(Eet_File *ef,
1064 const char *name,
1065 const char *cipher_key,
1066 Eio_Done_Read_Cb done_cb,
1067 Eio_Error_Cb error_cb,
1068 const void *data);
1069
1070/**
1071 * @brief Write a specified entry to an eet file handle using a cipher.
1072 * @param ef A valid eet file handle opened for writing.
1073 * @param name Name of the entry. eg: "/base/file_i_want".
1074 * @param write_data Pointer to the data to be stored.
1075 * @param size Length in bytes in the data to be stored.
1076 * @param compress Compression flags (1 == compress, 0 = don't compress).
1077 * @param cipher_key The key to use as cipher.
1078 * @param done_cb Callback called from the main loop when the data has been put in the Eet_File.
1079 * @param error_cb Callback called in the main loop when the file can't be written.
1080 * @param user_data Private data given to each callback.
1081 * @return NULL in case of a failure.
1082 */
1083EAPI Eio_File *eio_eet_write_cipher(Eet_File *ef,
1084 const char *name,
1085 void *write_data,
1086 int size,
1087 int compress,
1088 const char *cipher_key,
1089 Eio_Done_Int_Cb done_cb,
1090 Eio_Error_Cb error_cb,
1091 const void *user_data);
1092
1093/**
1094 * @}
1095 */
1096
1097/**
1098 * @defgroup Eio_Monitor Eio file and directory monitoring API
1099 *
1100 * @brief These function monitor changes in directories and files
1101 *
1102 * These functions use the best available method to monitor changes on a specified directory
1103 * or file. They send ecore events when changes occur, and they maintain internal refcounts to
1104 * reduce resource consumption on duplicate monitor targets.
1105 *
1106 * @{
1107 */
1108
1109EAPI extern int EIO_MONITOR_FILE_CREATED; /**< A new file was created in a watched directory */
1110EAPI extern int EIO_MONITOR_FILE_DELETED; /**< A watched file was deleted, or a file in a watched directory was deleted */
1111EAPI extern int EIO_MONITOR_FILE_MODIFIED; /**< A file was modified in a watched directory */
1112EAPI extern int EIO_MONITOR_FILE_CLOSED; /**< A file was closed in a watched directory. This event is never sent on Windows */
1113EAPI extern int EIO_MONITOR_DIRECTORY_CREATED; /**< A new directory was created in a watched directory */
1114EAPI extern int EIO_MONITOR_DIRECTORY_DELETED; /**< A directory has been deleted: this can be either a watched directory or one of its subdirectories */
1115EAPI extern int EIO_MONITOR_DIRECTORY_MODIFIED; /**< A directory has been modified in a watched directory */
1116EAPI extern int EIO_MONITOR_DIRECTORY_CLOSED; /**< A directory has been closed in a watched directory. This event is never sent on Windows */
1117EAPI extern int EIO_MONITOR_SELF_RENAME; /**< The monitored path has been renamed, an error could happen just after if the renamed path doesn't exist */
1118EAPI extern int EIO_MONITOR_SELF_DELETED; /**< The monitored path has been removed */
1119EAPI extern int EIO_MONITOR_ERROR; /**< During operation the monitor failed and will no longer work. eio_monitor_del must be called on it. */
1120
1121typedef struct _Eio_Monitor Eio_Monitor;
1122
1123typedef struct _Eio_Monitor_Error Eio_Monitor_Error;
1124typedef struct _Eio_Monitor_Event Eio_Monitor_Event;
1125
1126struct _Eio_Monitor_Error
1127{
1128 Eio_Monitor *monitor;
1129 int error;
1130};
1131
1132struct _Eio_Monitor_Event
1133{
1134 Eio_Monitor *monitor;
1135 const char *filename;
1136};
1137
1138/**
1139 * @brief Adds a file/directory to monitor (inotify mechanism)
1140 * @param path file/directory to monitor
1141 * @return NULL in case of a failure or a pointer to the monitor in case of
1142 * success.
1143 *
1144 * This function will add the given path to its internal
1145 * list of files to monitor. It utilizes the inotify mechanism
1146 * introduced in kernel 2.6.13 for passive monitoring.
1147 */
1148EAPI Eio_Monitor *eio_monitor_add(const char *path);
1149
1150/**
1151 * @brief Adds a file/directory to monitor
1152 * @param path file/directory to monitor
1153 * @return NULL in case of a failure or a pointer to the monitor in case of
1154 * success.
1155 * @warning Do NOT pass non-stringshared strings to this function!
1156 * If you don't know what this means, use eio_monitor_add().
1157 *
1158 * This fuction is just like eio_monitor_add(), however the string passed by
1159 * argument must be created using eina_stringshare_add().
1160 */
1161EAPI Eio_Monitor *eio_monitor_stringshared_add(const char *path);
1162
1163/**
1164 * @brief Deletes a path from the “watched” list
1165 * @param monitor The Eio_Monitor you want to stop watching.
1166 * It can only be an Eio_Monitor returned to you from calling
1167 * eio_monitor_add() or eio_monitor_stringshared_add()
1168 */
1169EAPI void eio_monitor_del(Eio_Monitor *monitor);
1170
1171/**
1172 * @brief returns the path being watched by the given
1173 * Eio_Monitor.
1174 * @param monitor Eio_Monitor to return the path of
1175 * @return The stringshared path belonging to @p monitor
1176 */
1177EAPI const char *eio_monitor_path_get(Eio_Monitor *monitor);
1178
1179/**
1180 * @}
1181 */
1182
1183#include "eio_inline_helper.x"
1184
1185#ifdef __cplusplus
1186}
1187#endif
1188
1189
1190#endif
diff --git a/src/lib/eio/eio_dir.c b/src/lib/eio/eio_dir.c
new file mode 100644
index 0000000000..71cc3a0540
--- /dev/null
+++ b/src/lib/eio/eio_dir.c
@@ -0,0 +1,1001 @@
1/* EIO - EFL data type library
2 * Copyright (C) 2010 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
31static int
32eio_strcmp(const void *a, const void *b)
33{
34 return strcmp(a, b);
35}
36static Eina_Bool
37_eio_dir_recursive_progress(Eio_Dir_Copy *copy, Eio_File *handler, const Eina_File_Direct_Info *info)
38{
39 if (copy->filter_cb && !copy->filter_cb(&copy->progress.common.data, handler, info))
40 return EINA_FALSE;
41
42 switch (info->type)
43 {
44 case EINA_FILE_UNKNOWN:
45 eio_file_thread_error(&copy->progress.common, handler->thread);
46 return EINA_FALSE;
47 case EINA_FILE_LNK:
48 copy->links = eina_list_append(copy->links, eina_stringshare_add(info->path));
49 break;
50 case EINA_FILE_DIR:
51 copy->dirs = eina_list_append(copy->dirs, eina_stringshare_add(info->path));
52 break;
53 default:
54 copy->files = eina_list_append(copy->files, eina_stringshare_add(info->path));
55 break;
56 }
57
58 return EINA_TRUE;
59}
60
61static Eina_Bool
62_eio_file_recursiv_ls(Ecore_Thread *thread,
63 Eio_File *common,
64 Eio_Filter_Direct_Cb filter_cb,
65 Eina_Iterator *(*Eina_File_Ls)(const char *target),
66 void *data,
67 const char *target)
68{
69 Eina_File_Direct_Info *info;
70 Eina_Iterator *it = NULL;
71 Eina_List *dirs = NULL;
72 const char *dir;
73
74 it = Eina_File_Ls(target);
75 if (!it)
76 {
77 eio_file_thread_error(common, thread);
78 return EINA_FALSE;
79 }
80
81 eio_file_container_set(common, eina_iterator_container_get(it));
82
83 EINA_ITERATOR_FOREACH(it, info)
84 {
85 Eina_Bool filter = EINA_TRUE;
86 _eio_stat_t buffer;
87
88 switch (info->type)
89 {
90 case EINA_FILE_DIR:
91 if (_eio_lstat(info->path, &buffer) != 0)
92 continue;
93
94 if (S_ISLNK(buffer.st_mode))
95 info->type = EINA_FILE_LNK;
96 default:
97 break;
98 }
99
100 filter = filter_cb(data, common, info);
101 if (filter && info->type == EINA_FILE_DIR)
102 dirs = eina_list_append(dirs, eina_stringshare_add(info->path));
103
104 if (ecore_thread_check(thread))
105 goto on_error;
106 }
107
108 eio_file_container_set(common, NULL);
109
110 eina_iterator_free(it);
111 it = NULL;
112
113 EINA_LIST_FREE(dirs, dir)
114 {
115 Eina_Bool err;
116
117 err = !_eio_file_recursiv_ls(thread, common, filter_cb, Eina_File_Ls, data, dir);
118
119 eina_stringshare_del(dir);
120 if (err) goto on_error;
121 }
122
123 return EINA_TRUE;
124
125 on_error:
126 if (it) eina_iterator_free(it);
127
128 EINA_LIST_FREE(dirs, dir)
129 eina_stringshare_del(dir);
130
131 return EINA_FALSE;
132}
133
134
135static Eina_Bool
136_eio_dir_recursiv_ls(Ecore_Thread *thread, Eio_Dir_Copy *copy, const char *target)
137{
138 if (!_eio_file_recursiv_ls(thread, &copy->progress.common,
139 (Eio_Filter_Direct_Cb) _eio_dir_recursive_progress,
140 eina_file_stat_ls,
141 copy, target))
142 return EINA_FALSE;
143
144 return EINA_TRUE;
145}
146
147static Eina_Bool
148_eio_dir_init(Ecore_Thread *thread,
149 long long *step, long long *count,
150 int *length_source, int *length_dest,
151 Eio_Dir_Copy *order,
152 Eio_File_Progress *progress)
153{
154 struct stat buffer;
155
156 /* notify main thread of the amount of work todo */
157 *step = 0;
158 *count = eina_list_count(order->files)
159 + eina_list_count(order->dirs) * 2
160 + eina_list_count(order->links);
161 eio_progress_send(thread, &order->progress, *step, *count);
162
163 /* sort the content, so we create the directory in the right order */
164 order->dirs = eina_list_sort(order->dirs, -1, eio_strcmp);
165 order->files = eina_list_sort(order->files, -1, eio_strcmp);
166 order->links = eina_list_sort(order->links, -1, eio_strcmp);
167
168 /* prepare stuff */
169 *length_source = eina_stringshare_strlen(order->progress.source);
170 *length_dest = eina_stringshare_strlen(order->progress.dest);
171
172 memcpy(progress, &order->progress, sizeof (Eio_File_Progress));
173 progress->source = NULL;
174 progress->dest = NULL;
175
176 /* create destination dir if not available */
177 if (stat(order->progress.dest, &buffer) != 0)
178 {
179 if (stat(order->progress.source, &buffer) != 0)
180 {
181 eio_file_thread_error(&order->progress.common, thread);
182 return EINA_FALSE;
183 }
184
185 if (mkdir(order->progress.dest, buffer.st_mode) != 0)
186 {
187 eio_file_thread_error(&order->progress.common, thread);
188 return EINA_FALSE;
189 }
190 }
191
192 return EINA_TRUE;
193}
194
195static void
196_eio_dir_target(Eio_Dir_Copy *order, char *target, const char *dir, int length_source, int length_dest)
197{
198 int length;
199
200 length = eina_stringshare_strlen(dir);
201
202 memcpy(target, order->progress.dest, length_dest);
203 target[length_dest] = '/';
204 memcpy(target + length_dest + 1, dir + length_source, length - length_source + 1);
205}
206
207static Eina_Bool
208_eio_dir_mkdir(Ecore_Thread *thread, Eio_Dir_Copy *order,
209 long long *step, long long count,
210 int length_source, int length_dest)
211{
212 const char *dir;
213 Eina_List *l;
214 char target[PATH_MAX];
215
216 /* create all directory */
217 EINA_LIST_FOREACH(order->dirs, l, dir)
218 {
219 /* build target dir path */
220 _eio_dir_target(order, target, dir, length_source, length_dest);
221
222 /* create the directory (we will apply the mode later) */
223 if (mkdir(target, 0777) != 0)
224 {
225 eio_file_thread_error(&order->progress.common, thread);
226 return EINA_FALSE;
227 }
228
229 /* inform main thread */
230 (*step)++;
231 eio_progress_send(thread, &order->progress, *step, count);
232
233 /* check for cancel request */
234 if (ecore_thread_check(thread))
235 return EINA_FALSE;
236 }
237
238 return EINA_TRUE;
239}
240
241static Eina_Bool
242_eio_dir_link(Ecore_Thread *thread, Eio_Dir_Copy *order,
243 long long *step, long long count,
244 int length_source, int length_dest)
245{
246 const char *ln;
247 Eina_List *l;
248 char oldpath[PATH_MAX];
249 char target[PATH_MAX];
250 char buffer[PATH_MAX];
251 char *newpath;
252
253 /* Build once the base of the link target */
254 memcpy(buffer, order->progress.dest, length_dest);
255 buffer[length_dest] = '/';
256
257 /* recreate all links */
258 EINA_LIST_FOREACH(order->links, l, ln)
259 {
260 ssize_t length;
261
262 /* build oldpath link */
263 _eio_dir_target(order, oldpath, ln, length_source, length_dest);
264
265 /* read link target */
266 length = readlink(ln, target, PATH_MAX);
267 if (length < 0)
268 goto on_error;
269
270 if (strncmp(target, order->progress.source, length_source) == 0)
271 {
272 /* The link is inside the zone to copy, so rename it */
273 memcpy(buffer + length_dest + 1, target + length_source, length - length_source + 1);
274 newpath = target;
275 }
276 else
277 {
278 /* The link is outside the zone to copy */
279 newpath = target;
280 }
281
282 /* create the link */
283 if (symlink(newpath, oldpath) != 0)
284 goto on_error;
285
286 /* inform main thread */
287 (*step)++;
288 eio_progress_send(thread, &order->progress, *step, count);
289
290 /* check for cancel request */
291 if (ecore_thread_check(thread))
292 return EINA_FALSE;
293 }
294
295 return EINA_TRUE;
296
297 on_error:
298 eio_file_thread_error(&order->progress.common, thread);
299 return EINA_FALSE;
300}
301
302static Eina_Bool
303_eio_dir_chmod(Ecore_Thread *thread, Eio_Dir_Copy *order,
304 long long *step, long long count,
305 int length_source, int length_dest,
306 Eina_Bool rmdir_source)
307{
308 const char *dir;
309 char target[PATH_MAX];
310 struct stat buffer;
311
312 while(order->dirs)
313 {
314 /* destroy in reverse order so that we don't prevent change of lower dir */
315 dir = eina_list_data_get(eina_list_last(order->dirs));
316 order->dirs = eina_list_remove_list(order->dirs, eina_list_last(order->dirs));
317
318 /* build target dir path */
319 _eio_dir_target(order, target, dir, length_source, length_dest);
320
321 /* FIXME: in some case we already did a stat call, so would be nice to reuse previous result here */
322 /* stat the original dir for mode info */
323 if (stat(dir, &buffer) != 0)
324 goto on_error;
325
326 /* set the orginal mode to the newly created dir */
327 if (chmod(target, buffer.st_mode) != 0)
328 goto on_error;
329
330 /* if required destroy original directory */
331 if (rmdir_source)
332 {
333 if (rmdir(dir) != 0)
334 goto on_error;
335 }
336
337 /* inform main thread */
338 (*step)++;
339 eio_progress_send(thread, &order->progress, *step, count);
340
341 /* check for cancel request */
342 if (ecore_thread_check(thread))
343 goto on_cancel;
344
345 eina_stringshare_del(dir);
346 }
347
348 return EINA_TRUE;
349
350 on_error:
351 eio_file_thread_error(&order->progress.common, thread);
352 on_cancel:
353 if (dir) eina_stringshare_del(dir);
354 return EINA_FALSE;
355}
356
357static void
358_eio_dir_copy_heavy(void *data, Ecore_Thread *thread)
359{
360 Eio_Dir_Copy *copy = data;
361 const char *file = NULL;
362 const char *dir;
363 const char *ln;
364
365 Eio_File_Progress file_copy;
366 char target[PATH_MAX];
367
368 int length_source = 0;
369 int length_dest = 0;
370 long long count;
371 long long step;
372
373 /* list all the content that should be copied */
374 if (!_eio_dir_recursiv_ls(thread, copy, copy->progress.source))
375 return ;
376
377 /* init all structure needed to copy the file */
378 if (!_eio_dir_init(thread, &step, &count, &length_source, &length_dest, copy, &file_copy))
379 goto on_error;
380
381 /* suboperation is a file copy */
382 file_copy.op = EIO_FILE_COPY;
383
384 /* create all directory */
385 if (!_eio_dir_mkdir(thread, copy, &step, count, length_source, length_dest))
386 goto on_error;
387
388 /* copy all files */
389 EINA_LIST_FREE(copy->files, file)
390 {
391 /* build target file path */
392 _eio_dir_target(copy, target, file, length_source, length_dest);
393
394 file_copy.source = file;
395 file_copy.dest = eina_stringshare_add(target);
396
397 /* copy the file */
398 if (!eio_file_copy_do(thread, &file_copy))
399 {
400 copy->progress.common.error = file_copy.common.error;
401 goto on_error;
402 }
403
404 /* notify main thread */
405 step++;
406 eio_progress_send(thread, &copy->progress, step, count);
407
408 if (ecore_thread_check(thread))
409 goto on_error;
410
411 eina_stringshare_del(file_copy.dest);
412 eina_stringshare_del(file);
413 }
414 file_copy.dest = NULL;
415 file = NULL;
416
417 /* recreate link */
418 if (!_eio_dir_link(thread, copy, &step, count, length_source, length_dest))
419 goto on_error;
420
421 /* set directory right back */
422 if (!_eio_dir_chmod(thread, copy, &step, count, length_source, length_dest, EINA_FALSE))
423 goto on_error;
424
425 on_error:
426 /* cleanup the mess */
427 if (file_copy.dest) eina_stringshare_del(file_copy.dest);
428 if (file) eina_stringshare_del(file);
429
430 EINA_LIST_FREE(copy->files, file)
431 eina_stringshare_del(file);
432 EINA_LIST_FREE(copy->dirs, dir)
433 eina_stringshare_del(dir);
434 EINA_LIST_FREE(copy->links, ln)
435 eina_stringshare_del(ln);
436
437 if (!ecore_thread_check(thread))
438 eio_progress_send(thread, &copy->progress, count, count);
439
440 return ;
441}
442
443static void
444_eio_dir_copy_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
445{
446 Eio_Dir_Copy *copy = data;
447 Eio_Progress *progress = msg_data;
448
449 eio_progress_cb(progress, &copy->progress);
450}
451
452static void
453_eio_dir_copy_free(Eio_Dir_Copy *copy)
454{
455 eina_stringshare_del(copy->progress.source);
456 eina_stringshare_del(copy->progress.dest);
457 eio_file_free(&copy->progress.common);
458}
459
460static void
461_eio_dir_copy_end(void *data, Ecore_Thread *thread EINA_UNUSED)
462{
463 Eio_Dir_Copy *copy = data;
464
465 copy->progress.common.done_cb((void*) copy->progress.common.data, &copy->progress.common);
466
467 _eio_dir_copy_free(copy);
468}
469
470static void
471_eio_dir_copy_error(void *data, Ecore_Thread *thread EINA_UNUSED)
472{
473 Eio_Dir_Copy *copy = data;
474
475 eio_file_error(&copy->progress.common);
476
477 _eio_dir_copy_free(copy);
478}
479
480static void
481_eio_dir_move_heavy(void *data, Ecore_Thread *thread)
482{
483 Eio_Dir_Copy *move = data;
484 const char *file = NULL;
485 const char *dir = NULL;
486
487 Eio_File_Progress file_move;
488 char target[PATH_MAX];
489
490 int length_source;
491 int length_dest;
492 long long count;
493 long long step;
494
495 /* just try a rename, maybe we are lucky... */
496 if (rename(move->progress.source, move->progress.dest) == 0)
497 {
498 /* we are really lucky */
499 eio_progress_send(thread, &move->progress, 1, 1);
500 return ;
501 }
502
503 /* list all the content that should be moved */
504 if (!_eio_dir_recursiv_ls(thread, move, move->progress.source))
505 return ;
506
507 /* init all structure needed to move the file */
508 if (!_eio_dir_init(thread, &step, &count, &length_source, &length_dest, move, &file_move))
509 goto on_error;
510
511 /* sub operation is a file move */
512 file_move.op = EIO_FILE_MOVE;
513
514 /* create all directory */
515 if (!_eio_dir_mkdir(thread, move, &step, count, length_source, length_dest))
516 goto on_error;
517
518 /* move file around */
519 EINA_LIST_FREE(move->files, file)
520 {
521 /* build target file path */
522 _eio_dir_target(move, target, file, length_source, length_dest);
523
524 file_move.source = file;
525 file_move.dest = eina_stringshare_add(target);
526
527 /* first try to rename */
528 if (rename(file_move.source, file_move.dest) < 0)
529 {
530 if (errno != EXDEV)
531 {
532 eio_file_thread_error(&move->progress.common, thread);
533 goto on_error;
534 }
535
536 /* then try real copy */
537 if (!eio_file_copy_do(thread, &file_move))
538 {
539 move->progress.common.error = file_move.common.error;
540 goto on_error;
541 }
542
543 /* and unlink the original */
544 if (unlink(file) != 0)
545 {
546 eio_file_thread_error(&move->progress.common, thread);
547 goto on_error;
548 }
549 }
550
551 step++;
552 eio_progress_send(thread, &move->progress, step, count);
553
554 if (ecore_thread_check(thread))
555 goto on_error;
556
557 eina_stringshare_del(file_move.dest);
558 eina_stringshare_del(file);
559 }
560 file_move.dest = NULL;
561 file = NULL;
562
563 /* recreate link */
564 if (!_eio_dir_link(thread, move, &step, count, length_source, length_dest))
565 goto on_error;
566
567 /* set directory right back */
568 if (!_eio_dir_chmod(thread, move, &step, count, length_source, length_dest, EINA_TRUE))
569 goto on_error;
570
571 if (rmdir(move->progress.source) != 0)
572 goto on_error;
573
574 on_error:
575 /* cleanup the mess */
576 if (file_move.dest) eina_stringshare_del(file_move.dest);
577 if (file) eina_stringshare_del(file);
578
579 EINA_LIST_FREE(move->files, file)
580 eina_stringshare_del(file);
581 EINA_LIST_FREE(move->dirs, dir)
582 eina_stringshare_del(dir);
583
584 if (!ecore_thread_check(thread))
585 eio_progress_send(thread, &move->progress, count, count);
586
587 return;
588}
589
590static void
591_eio_dir_rmrf_heavy(void *data, Ecore_Thread *thread)
592{
593 Eio_Dir_Copy *rmrf = data;
594 const char *file = NULL;
595 const char *dir = NULL;
596
597 long long count;
598 long long step;
599
600 /* list all the content that should be moved */
601 if (!_eio_dir_recursiv_ls(thread, rmrf, rmrf->progress.source))
602 return ;
603
604 /* init counter */
605 step = 0;
606 count = eina_list_count(rmrf->files) + eina_list_count(rmrf->dirs) + 1;
607
608 EINA_LIST_FREE(rmrf->files, file)
609 {
610 if (unlink(file) != 0)
611 {
612 eio_file_thread_error(&rmrf->progress.common, thread);
613 goto on_error;
614 }
615
616 eina_stringshare_replace(&rmrf->progress.dest, file);
617
618 step++;
619 eio_progress_send(thread, &rmrf->progress, step, count);
620
621 if (ecore_thread_check(thread))
622 goto on_error;
623
624 eina_stringshare_del(file);
625 }
626 file = NULL;
627
628 /* reverse directory listing, so the leaf would be destroyed before
629 the root */
630 rmrf->dirs = eina_list_reverse(rmrf->dirs);
631
632 EINA_LIST_FREE(rmrf->dirs, dir)
633 {
634 if (rmdir(dir) != 0)
635 {
636 eio_file_thread_error(&rmrf->progress.common, thread);
637 goto on_error;
638 }
639
640 eina_stringshare_replace(&rmrf->progress.dest, dir);
641
642 step++;
643 eio_progress_send(thread, &rmrf->progress, step, count);
644
645 if (ecore_thread_check(thread))
646 goto on_error;
647
648 eina_stringshare_del(dir);
649 }
650 dir = NULL;
651
652 if (rmdir(rmrf->progress.source) != 0)
653 goto on_error;
654 step++;
655
656 on_error:
657 if (dir) eina_stringshare_del(dir);
658 if (file) eina_stringshare_del(file);
659
660 EINA_LIST_FREE(rmrf->dirs, dir)
661 eina_stringshare_del(dir);
662 EINA_LIST_FREE(rmrf->files, file)
663 eina_stringshare_del(file);
664
665 if (!ecore_thread_check(thread))
666 eio_progress_send(thread, &rmrf->progress, count, count);
667
668 return;
669}
670
671static Eina_Bool
672_eio_dir_stat_find_forward(Eio_File_Dir_Ls *async,
673 Eio_File *handler,
674 Eina_File_Direct_Info *info)
675{
676 Eina_Bool filter = EINA_TRUE;
677 double current;
678
679 if (async->filter_cb)
680 {
681 filter = async->filter_cb((void*) async->ls.common.data, &async->ls.common, info);
682 }
683
684 if (filter)
685 {
686 Eio_File_Direct_Info *send_di;
687
688 send_di = eio_direct_info_malloc();
689 if (!send_di) return EINA_FALSE;
690
691 memcpy(&send_di->info, info, sizeof (Eina_File_Direct_Info));
692 send_di->associated = async->ls.common.worker.associated;
693 async->ls.common.worker.associated = NULL;
694
695 async->pack = eina_list_append(async->pack, send_di);
696 }
697 else if (async->ls.common.worker.associated)
698 {
699 eina_hash_free(async->ls.common.worker.associated);
700 async->ls.common.worker.associated = NULL;
701 }
702
703 current = ecore_time_get();
704 if (current - async->start > EIO_PACKED_TIME)
705 {
706 async->start = current;
707 ecore_thread_feedback(handler->thread, async->pack);
708 async->pack = NULL;
709 }
710
711 return filter;
712}
713
714static void
715_eio_dir_stat_find_heavy(void *data, Ecore_Thread *thread)
716{
717 Eio_File_Dir_Ls *async = data;
718
719 async->ls.common.thread = thread;
720 async->pack = NULL;
721 async->start = ecore_time_get();
722
723 _eio_file_recursiv_ls(thread, &async->ls.common,
724 (Eio_Filter_Direct_Cb) _eio_dir_stat_find_forward,
725 eina_file_stat_ls,
726 async, async->ls.directory);
727
728 if (async->pack) ecore_thread_feedback(thread, async->pack);
729 async->pack = NULL;
730}
731
732static void
733_eio_dir_direct_find_heavy(void *data, Ecore_Thread *thread)
734{
735 Eio_File_Dir_Ls *async = data;
736
737 async->ls.common.thread = thread;
738 async->pack = NULL;
739 async->start = ecore_time_get();
740
741 _eio_file_recursiv_ls(thread, &async->ls.common,
742 (Eio_Filter_Direct_Cb) _eio_dir_stat_find_forward,
743 eina_file_direct_ls,
744 async, async->ls.directory);
745
746 if (async->pack) ecore_thread_feedback(thread, async->pack);
747 async->pack = NULL;
748}
749
750static void
751_eio_dir_stat_find_notify(void *data, Ecore_Thread *thread EINA_UNUSED, void *msg_data)
752{
753 Eio_File_Dir_Ls *async = data;
754 Eina_List *pack = msg_data;
755 Eio_File_Direct_Info *info;
756
757 EINA_LIST_FREE(pack, info)
758 {
759 async->ls.common.main.associated = info->associated;
760
761 async->main_cb((void*) async->ls.common.data, &async->ls.common, &info->info);
762
763 if (async->ls.common.main.associated)
764 {
765 eina_hash_free(async->ls.common.main.associated);
766 async->ls.common.main.associated = NULL;
767 }
768
769 eio_direct_info_free(info);
770 }
771}
772
773static void
774_eio_dir_stat_done(void *data, Ecore_Thread *thread EINA_UNUSED)
775{
776 Eio_File_Ls *async = data;
777
778 async->common.done_cb((void*) async->common.data, &async->common);
779
780 eio_async_free(async);
781}
782
783static void
784_eio_dir_stat_error(void *data, Ecore_Thread *thread EINA_UNUSED)
785{
786 Eio_File_Ls *async = data;
787
788 eio_file_error(&async->common);
789
790 eio_async_free(async);
791}
792
793/**
794 * @endcond
795 */
796
797/*============================================================================*
798 * Global *
799 *============================================================================*/
800
801
802/*============================================================================*
803 * API *
804 *============================================================================*/
805
806
807EAPI Eio_File *
808eio_dir_copy(const char *source,
809 const char *dest,
810 Eio_Filter_Direct_Cb filter_cb,
811 Eio_Progress_Cb progress_cb,
812 Eio_Done_Cb done_cb,
813 Eio_Error_Cb error_cb,
814 const void *data)
815{
816 Eio_Dir_Copy *copy;
817
818 EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL);
819 EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL);
820 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
821 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
822
823 copy = malloc(sizeof(Eio_Dir_Copy));
824 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, NULL);
825
826 copy->progress.op = EIO_DIR_COPY;
827 copy->progress.progress_cb = progress_cb;
828 copy->progress.source = eina_stringshare_add(source);
829 copy->progress.dest = eina_stringshare_add(dest);
830 copy->filter_cb = filter_cb;
831 copy->files = NULL;
832 copy->dirs = NULL;
833 copy->links = NULL;
834
835 if (!eio_long_file_set(&copy->progress.common,
836 done_cb,
837 error_cb,
838 data,
839 _eio_dir_copy_heavy,
840 _eio_dir_copy_notify,
841 _eio_dir_copy_end,
842 _eio_dir_copy_error))
843 return NULL;
844
845 return &copy->progress.common;
846}
847
848EAPI Eio_File *
849eio_dir_move(const char *source,
850 const char *dest,
851 Eio_Filter_Direct_Cb filter_cb,
852 Eio_Progress_Cb progress_cb,
853 Eio_Done_Cb done_cb,
854 Eio_Error_Cb error_cb,
855 const void *data)
856{
857 Eio_Dir_Copy *move;
858
859 EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL);
860 EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL);
861 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
862 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
863
864 move = malloc(sizeof(Eio_Dir_Copy));
865 EINA_SAFETY_ON_NULL_RETURN_VAL(move, NULL);
866
867 move->progress.op = EIO_DIR_MOVE;
868 move->progress.progress_cb = progress_cb;
869 move->progress.source = eina_stringshare_add(source);
870 move->progress.dest = eina_stringshare_add(dest);
871 move->filter_cb = filter_cb;
872 move->files = NULL;
873 move->dirs = NULL;
874 move->links = NULL;
875
876 if (!eio_long_file_set(&move->progress.common,
877 done_cb,
878 error_cb,
879 data,
880 _eio_dir_move_heavy,
881 _eio_dir_copy_notify,
882 _eio_dir_copy_end,
883 _eio_dir_copy_error))
884 return NULL;
885
886 return &move->progress.common;
887}
888
889EAPI Eio_File *
890eio_dir_unlink(const char *path,
891 Eio_Filter_Direct_Cb filter_cb,
892 Eio_Progress_Cb progress_cb,
893 Eio_Done_Cb done_cb,
894 Eio_Error_Cb error_cb,
895 const void *data)
896{
897 Eio_Dir_Copy *rmrf;
898
899 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
900 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
901 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
902
903 rmrf = malloc(sizeof(Eio_Dir_Copy));
904 EINA_SAFETY_ON_NULL_RETURN_VAL(rmrf, NULL);
905
906 rmrf->progress.op = EIO_UNLINK;
907 rmrf->progress.progress_cb = progress_cb;
908 rmrf->progress.source = eina_stringshare_add(path);
909 rmrf->progress.dest = NULL;
910 rmrf->filter_cb = filter_cb;
911 rmrf->files = NULL;
912 rmrf->dirs = NULL;
913 rmrf->links = NULL;
914
915 if (!eio_long_file_set(&rmrf->progress.common,
916 done_cb,
917 error_cb,
918 data,
919 _eio_dir_rmrf_heavy,
920 _eio_dir_copy_notify,
921 _eio_dir_copy_end,
922 _eio_dir_copy_error))
923 return NULL;
924
925 return &rmrf->progress.common;
926}
927
928EAPI Eio_File *
929eio_dir_stat_ls(const char *dir,
930 Eio_Filter_Direct_Cb filter_cb,
931 Eio_Main_Direct_Cb main_cb,
932 Eio_Done_Cb done_cb,
933 Eio_Error_Cb error_cb,
934 const void *data)
935{
936 Eio_File_Dir_Ls *async;
937
938 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
939 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
940 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
941 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
942
943 async = malloc(sizeof(Eio_File_Dir_Ls));
944 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
945
946 /* Eio_Filter_Direct_Cb must be casted to Eio_Filter_Dir_Cb here
947 * because we keep the Eio_File_Dir_Ls pointing to that variant
948 * where info can be modified, but in our case it's already doing
949 * stat() then it shouldn't be needed!
950 */
951 async->filter_cb = (Eio_Filter_Dir_Cb)filter_cb;
952 async->main_cb = main_cb;
953 async->ls.directory = eina_stringshare_add(dir);
954
955 if (!eio_long_file_set(&async->ls.common,
956 done_cb,
957 error_cb,
958 data,
959 _eio_dir_stat_find_heavy,
960 _eio_dir_stat_find_notify,
961 _eio_dir_stat_done,
962 _eio_dir_stat_error))
963 return NULL;
964
965 return &async->ls.common;
966}
967
968EAPI Eio_File *
969eio_dir_direct_ls(const char *dir,
970 Eio_Filter_Dir_Cb filter_cb,
971 Eio_Main_Direct_Cb main_cb,
972 Eio_Done_Cb done_cb,
973 Eio_Error_Cb error_cb,
974 const void *data)
975{
976 Eio_File_Dir_Ls *async;
977
978 EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL);
979 EINA_SAFETY_ON_NULL_RETURN_VAL(main_cb, NULL);
980 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
981 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
982
983 async = malloc(sizeof(Eio_File_Dir_Ls));
984 EINA_SAFETY_ON_NULL_RETURN_VAL(async, NULL);
985
986 async->filter_cb = filter_cb;
987 async->main_cb = main_cb;
988 async->ls.directory = eina_stringshare_add(dir);
989
990 if (!eio_long_file_set(&async->ls.common,
991 done_cb,
992 error_cb,
993 data,
994 _eio_dir_direct_find_heavy,
995 _eio_dir_stat_find_notify,
996 _eio_dir_stat_done,
997 _eio_dir_stat_error))
998 return NULL;
999
1000 return &async->ls.common;
1001}
diff --git a/src/lib/eio/eio_eet.c b/src/lib/eio/eio_eet.c
new file mode 100644
index 0000000000..c25cc4a035
--- /dev/null
+++ b/src/lib/eio/eio_eet.c
@@ -0,0 +1,640 @@
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
33static void
34_eio_eet_open_job(void *data, Ecore_Thread *thread)
35{
36 Eio_Eet_Open *eet = data;
37
38 eet->result = eet_open(eet->filename, eet->mode);
39 if (!eet->result) eio_file_thread_error(&eet->common, thread);
40}
41
42static void
43_eio_eet_open_free(Eio_Eet_Open *eet)
44{
45 if (eet->filename) eina_stringshare_del(eet->filename);
46 free(eet);
47}
48
49static void
50_eio_eet_open_end(void *data, Ecore_Thread *thread EINA_UNUSED)
51{
52 Eio_Eet_Open *eet = data;
53
54 eet->eet_cb((void*) eet->common.data, &eet->common, eet->result);
55 _eio_eet_open_free(eet);
56}
57
58static void
59_eio_eet_open_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
60{
61 Eio_Eet_Open *eet = data;
62
63 eio_file_error(&eet->common);
64 _eio_eet_open_free(eet);
65}
66
67static void
68_eio_eet_close_job(void *data, Ecore_Thread *thread)
69{
70 Eio_Eet_Simple *eet = data;
71
72 eet->error = eet_close(eet->ef);
73 if (eet->error != EET_ERROR_NONE) eio_file_thread_error(&eet->common, thread);
74}
75
76static void
77_eio_eet_sync_job(void *data, Ecore_Thread *thread)
78{
79 Eio_Eet_Simple *eet = data;
80
81 eet->error = eet_sync(eet->ef);
82 if (eet->error != EET_ERROR_NONE) eio_file_thread_error(&eet->common, thread);
83}
84
85static void
86_eio_eet_simple_end(void *data, Ecore_Thread *thread EINA_UNUSED)
87{
88 Eio_Eet_Simple *eet = data;
89
90 eet->common.done_cb((void*) eet->common.data, &eet->common);
91 free(eet);
92}
93
94static void
95_eio_eet_simple_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
96{
97 Eio_Eet_Simple *eet = data;
98
99 eet->error_cb((void*) eet->common.data, &eet->common, eet->error);
100 free(eet);
101}
102
103static void
104_eio_eet_data_write_cipher_job(void *data, Ecore_Thread *thread)
105{
106 Eio_Eet_Write *ew = data;
107
108 ew->result = eet_data_write_cipher(ew->ef, ew->edd,
109 ew->name, ew->cipher_key,
110 ew->write_data,
111 ew->compress);
112 if (ew->result == 0) eio_file_thread_error(&ew->common, thread);
113}
114
115static void
116_eio_eet_write_cipher_free(Eio_Eet_Write *ew)
117{
118 eina_stringshare_del(ew->name);
119 eina_stringshare_del(ew->cipher_key);
120 free(ew);
121}
122
123static void
124_eio_eet_data_write_cipher_end(void *data, Ecore_Thread *thread EINA_UNUSED)
125{
126 Eio_Eet_Write *ew = data;
127
128 ew->done_cb((void*) ew->common.data, &ew->common, ew->result);
129 _eio_eet_write_cipher_free(ew);
130}
131
132static void
133_eio_eet_data_write_cipher_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
134{
135 Eio_Eet_Write *ew = data;
136
137 eio_file_error(&ew->common);
138 _eio_eet_write_cipher_free(ew);
139}
140
141static void
142_eio_eet_image_write_job(void *data, Ecore_Thread *thread)
143{
144 Eio_Eet_Image_Write *eiw = data;
145
146 eiw->result = eet_data_image_write_cipher(eiw->ef, eiw->name, eiw->cipher_key,
147 eiw->write_data,
148 eiw->w,
149 eiw->h,
150 eiw->alpha,
151 eiw->compress,
152 eiw->quality,
153 eiw->lossy);
154 if (!eiw->result) eio_file_thread_error(&eiw->common, thread);
155}
156
157static void
158_eio_eet_image_write_free(Eio_Eet_Image_Write *eiw)
159{
160 eina_stringshare_del(eiw->name);
161 eina_stringshare_del(eiw->cipher_key);
162 free(eiw);
163}
164
165static void
166_eio_eet_image_write_end(void *data, Ecore_Thread *thread EINA_UNUSED)
167{
168 Eio_Eet_Image_Write *eiw = data;
169
170 eiw->done_cb((void*) eiw->common.data, &eiw->common, eiw->result);
171 _eio_eet_image_write_free(eiw);
172}
173
174static void
175_eio_eet_image_write_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
176{
177 Eio_Eet_Image_Write *eiw = data;
178
179 eio_file_error(&eiw->common);
180 _eio_eet_image_write_free(eiw);
181}
182
183static void
184_eio_eet_write_job(void *data, Ecore_Thread *thread)
185{
186 Eio_Eet_Write *ew = data;
187
188 ew->result = eet_write_cipher(ew->ef,
189 ew->name, ew->write_data,
190 ew->size, ew->compress,
191 ew->cipher_key);
192 if (!ew->result) eio_file_thread_error(&ew->common, thread);
193}
194
195static void
196_eio_eet_write_end(void *data, Ecore_Thread *thread EINA_UNUSED)
197{
198 Eio_Eet_Write *ew = data;
199
200 ew->done_cb((void*) ew->common.data, &ew->common, ew->result);
201 _eio_eet_write_cipher_free(ew);
202}
203
204static void
205_eio_eet_write_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
206{
207 Eio_Eet_Write *ew = data;
208
209 eio_file_error(&ew->common);
210 _eio_eet_write_cipher_free(ew);
211}
212
213static void
214_eio_eet_data_read_cipher_job(void *data, Ecore_Thread *thread)
215{
216 Eio_Eet_Read *er = data;
217
218 er->result = eet_data_read_cipher(er->ef, er->edd,
219 er->name, er->cipher_key);
220 if (!er->result) eio_file_thread_error(&er->common, thread);
221}
222
223static void
224_eio_eet_read_free(Eio_Eet_Read *er)
225{
226 eina_stringshare_del(er->name);
227 eina_stringshare_del(er->cipher_key);
228 free(er);
229}
230
231static void
232_eio_eet_data_read_cipher_end(void *data, Ecore_Thread *thread EINA_UNUSED)
233{
234 Eio_Eet_Read *er = data;
235
236 er->done_cb.eread((void*) er->common.data, &er->common, er->result);
237 _eio_eet_read_free(er);
238}
239
240static void
241_eio_eet_data_read_cipher_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
242{
243 Eio_Eet_Read *er = data;
244
245 eio_file_error(&er->common);
246 _eio_eet_read_free(er);
247}
248
249static void
250_eio_eet_read_direct_job(void *data, Ecore_Thread *thread)
251{
252 Eio_Eet_Read *er = data;
253
254 er->result = (void*) eet_read_direct(er->ef, er->name, &er->size);
255 if (!er->result) eio_file_thread_error(&er->common, thread);
256}
257
258static void
259_eio_eet_read_direct_end(void *data, Ecore_Thread *thread EINA_UNUSED)
260{
261 Eio_Eet_Read *er = data;
262
263 er->done_cb.data((void*) er->common.data, &er->common,
264 er->result, er->size);
265 _eio_eet_read_free(er);
266}
267
268static void
269_eio_eet_read_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
270{
271 Eio_Eet_Read *er = data;
272
273 eio_file_error(&er->common);
274 _eio_eet_read_free(er);
275}
276
277static void
278_eio_eet_read_cipher_job(void *data, Ecore_Thread *thread)
279{
280 Eio_Eet_Read *er = data;
281
282 er->result = (void*) eet_read_cipher(er->ef, er->name,
283 &er->size, er->cipher_key);
284 if (!er->result) eio_file_thread_error(&er->common, thread);
285}
286
287static void
288_eio_eet_read_cipher_end(void *data, Ecore_Thread *thread EINA_UNUSED)
289{
290 Eio_Eet_Read *er = data;
291
292 er->done_cb.read((void*) er->common.data, &er->common,
293 er->result, er->size);
294 _eio_eet_read_free(er);
295}
296
297/**
298 * @endcond
299 */
300
301/*============================================================================*
302 * Global *
303 *============================================================================*/
304
305
306/*============================================================================*
307 * API *
308 *============================================================================*/
309
310EAPI Eio_File *
311eio_eet_open(const char *filename,
312 Eet_File_Mode mode,
313 Eio_Eet_Open_Cb eet_cb,
314 Eio_Error_Cb error_cb,
315 const void *data)
316{
317 Eio_Eet_Open *eet;
318
319 EINA_SAFETY_ON_NULL_RETURN_VAL(filename, NULL);
320 EINA_SAFETY_ON_NULL_RETURN_VAL(eet_cb, NULL);
321 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
322
323 eet = malloc(sizeof (Eio_Eet_Open));
324 EINA_SAFETY_ON_NULL_RETURN_VAL(eet, NULL);
325
326 eet->eet_cb = eet_cb;
327 eet->filename = eina_stringshare_add(filename);
328 eet->mode = mode;
329 eet->result = NULL;
330
331 if (!eio_file_set(&eet->common,
332 NULL,
333 error_cb,
334 data,
335 _eio_eet_open_job,
336 _eio_eet_open_end,
337 _eio_eet_open_cancel))
338 return NULL;
339 return &eet->common;
340}
341
342EAPI Eio_File *
343eio_eet_close(Eet_File *ef,
344 Eio_Done_Cb done_cb,
345 Eio_Eet_Error_Cb error_cb,
346 const void *data)
347{
348 Eio_Eet_Simple *eet;
349
350 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
351 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
352 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
353
354 eet = malloc(sizeof (Eio_Eet_Simple));
355 EINA_SAFETY_ON_NULL_RETURN_VAL(eet, NULL);
356
357 eet->ef = ef;
358 eet->error_cb = error_cb;
359 eet->error = EET_ERROR_NONE;
360
361 if (!eio_file_set(&eet->common,
362 done_cb,
363 NULL,
364 data,
365 _eio_eet_close_job,
366 _eio_eet_simple_end,
367 _eio_eet_simple_cancel))
368 return NULL;
369 return &eet->common;
370}
371
372EAPI Eio_File *
373eio_eet_flush(Eet_File *ef,
374 Eio_Done_Cb done_cb,
375 Eio_Eet_Error_Cb error_cb,
376 const void *data)
377{
378 Eio_Eet_Simple *eet;
379
380 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
381 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
382 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
383
384 eet = malloc(sizeof (Eio_Eet_Simple));
385 EINA_SAFETY_ON_NULL_RETURN_VAL(eet, NULL);
386
387 eet->ef = ef;
388 eet->error_cb = error_cb;
389 eet->error = EET_ERROR_NONE;
390
391 if (!eio_file_set(&eet->common,
392 done_cb,
393 NULL,
394 data,
395 _eio_eet_sync_job,
396 _eio_eet_simple_end,
397 _eio_eet_simple_cancel))
398 return NULL;
399 return &eet->common;
400}
401
402EAPI Eio_File *
403eio_eet_data_write_cipher(Eet_File *ef,
404 Eet_Data_Descriptor *edd,
405 const char *name,
406 const char *cipher_key,
407 void *write_data,
408 int compress,
409 Eio_Done_Int_Cb done_cb,
410 Eio_Error_Cb error_cb,
411 const void *user_data)
412{
413 Eio_Eet_Write *ew;
414
415 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
416 EINA_SAFETY_ON_NULL_RETURN_VAL(edd, NULL);
417 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
418 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
419 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
420
421 ew = malloc(sizeof (Eio_Eet_Write));
422 EINA_SAFETY_ON_NULL_RETURN_VAL(ew, NULL);
423
424 ew->ef = ef;
425 ew->edd = edd;
426 ew->name = eina_stringshare_add(name);
427 ew->cipher_key = eina_stringshare_add(cipher_key);
428 ew->write_data = write_data;
429 ew->compress = compress;
430 ew->done_cb = done_cb;
431 ew->result = 0;
432
433 if (!eio_file_set(&ew->common,
434 NULL,
435 error_cb,
436 user_data,
437 _eio_eet_data_write_cipher_job,
438 _eio_eet_data_write_cipher_end,
439 _eio_eet_data_write_cipher_cancel))
440 return NULL;
441 return &ew->common;
442}
443
444EAPI Eio_File *
445eio_eet_data_read_cipher(Eet_File *ef,
446 Eet_Data_Descriptor *edd,
447 const char *name,
448 const char *cipher_key,
449 Eio_Done_ERead_Cb done_cb,
450 Eio_Error_Cb error_cb,
451 const void *data)
452{
453 Eio_Eet_Read *er;
454
455 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
456 EINA_SAFETY_ON_NULL_RETURN_VAL(edd, NULL);
457 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
458 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
459 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
460
461 er = malloc(sizeof (Eio_Eet_Read));
462 EINA_SAFETY_ON_NULL_RETURN_VAL(er, NULL);
463
464 er->ef = ef;
465 er->edd = edd;
466 er->name = eina_stringshare_add(name);
467 er->cipher_key = eina_stringshare_add(cipher_key);
468 er->done_cb.eread = done_cb;
469
470 if (!eio_file_set(&er->common,
471 NULL,
472 error_cb,
473 data,
474 _eio_eet_data_read_cipher_job,
475 _eio_eet_data_read_cipher_end,
476 _eio_eet_data_read_cipher_cancel))
477 return NULL;
478
479 return &er->common;
480}
481
482EAPI Eio_File *
483eio_eet_data_image_write_cipher(Eet_File *ef,
484 const char *name,
485 const char *cipher_key,
486 void *write_data,
487 unsigned int w,
488 unsigned int h,
489 int alpha,
490 int compress,
491 int quality,
492 int lossy,
493 Eio_Done_Int_Cb done_cb,
494 Eio_Error_Cb error_cb,
495 const void *user_data)
496{
497 Eio_Eet_Image_Write *eiw;
498
499 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
500 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
501 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
502 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
503
504 eiw = malloc(sizeof (Eio_Eet_Image_Write));
505 EINA_SAFETY_ON_NULL_RETURN_VAL(eiw, NULL);
506
507 eiw->ef = ef;
508 eiw->name = eina_stringshare_add(name);
509 eiw->cipher_key = eina_stringshare_add(cipher_key);
510 eiw->write_data = write_data;
511 eiw->w = w;
512 eiw->h = h;
513 eiw->alpha = alpha;
514 eiw->compress = compress;
515 eiw->quality = quality;
516 eiw->lossy = lossy;
517 eiw->done_cb = done_cb;
518 eiw->result = 0;
519
520 if (!eio_file_set(&eiw->common,
521 NULL,
522 error_cb,
523 user_data,
524 _eio_eet_image_write_job,
525 _eio_eet_image_write_end,
526 _eio_eet_image_write_cancel))
527 return NULL;
528 return &eiw->common;
529}
530
531EAPI Eio_File *
532eio_eet_read_direct(Eet_File *ef,
533 const char *name,
534 Eio_Done_Data_Cb done_cb,
535 Eio_Error_Cb error_cb,
536 const void *data)
537{
538 Eio_Eet_Read *er;
539
540 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
541 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
542 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
543 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
544
545 er = malloc(sizeof (Eio_Eet_Read));
546 EINA_SAFETY_ON_NULL_RETURN_VAL(er, NULL);
547
548 er->ef = ef;
549 er->name = eina_stringshare_add(name);
550 er->cipher_key = NULL;
551 er->done_cb.data = done_cb;
552 er->result = NULL;
553
554 if (!eio_file_set(&er->common,
555 NULL,
556 error_cb,
557 data,
558 _eio_eet_read_direct_job,
559 _eio_eet_read_direct_end,
560 _eio_eet_read_cancel))
561 return NULL;
562
563 return &er->common;
564}
565
566EAPI Eio_File *
567eio_eet_read_cipher(Eet_File *ef,
568 const char *name,
569 const char *cipher_key,
570 Eio_Done_Read_Cb done_cb,
571 Eio_Error_Cb error_cb,
572 const void *data)
573{
574 Eio_Eet_Read *er;
575
576 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
577 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
578 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
579 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
580
581 er = malloc(sizeof (Eio_Eet_Read));
582 EINA_SAFETY_ON_NULL_RETURN_VAL(er, NULL);
583
584 er->ef = ef;
585 er->name = eina_stringshare_add(name);
586 er->cipher_key = eina_stringshare_add(cipher_key);
587 er->done_cb.read = done_cb;
588 er->result = NULL;
589
590 if (!eio_file_set(&er->common,
591 NULL,
592 error_cb,
593 data,
594 _eio_eet_read_cipher_job,
595 _eio_eet_read_cipher_end,
596 _eio_eet_read_cancel))
597 return NULL;
598 return &er->common;
599}
600
601EAPI Eio_File *
602eio_eet_write_cipher(Eet_File *ef,
603 const char *name,
604 void *write_data,
605 int size,
606 int compress,
607 const char *cipher_key,
608 Eio_Done_Int_Cb done_cb,
609 Eio_Error_Cb error_cb,
610 const void *user_data)
611{
612 Eio_Eet_Write *ew;
613
614 EINA_SAFETY_ON_NULL_RETURN_VAL(ef, NULL);
615 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
616 EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, NULL);
617 EINA_SAFETY_ON_NULL_RETURN_VAL(error_cb, NULL);
618
619 ew = malloc(sizeof (Eio_Eet_Write));
620 EINA_SAFETY_ON_NULL_RETURN_VAL(ew, NULL);
621
622 ew->ef = ef;
623 ew->name = eina_stringshare_add(name);
624 ew->cipher_key = eina_stringshare_add(cipher_key);
625 ew->write_data = write_data;
626 ew->size = size;
627 ew->compress = compress;
628 ew->done_cb = done_cb;
629 ew->result = 0;
630
631 if (!eio_file_set(&ew->common,
632 NULL,
633 error_cb,
634 user_data,
635 _eio_eet_write_job,
636 _eio_eet_write_end,
637 _eio_eet_write_cancel))
638 return NULL;
639 return &ew->common;
640}
diff --git a/src/lib/eio/eio_file.c b/src/lib/eio/eio_file.c
new file mode 100644
index 0000000000..ffcd2a73ad
--- /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}
diff --git a/src/lib/eio/eio_inline_helper.x b/src/lib/eio/eio_inline_helper.x
new file mode 100644
index 0000000000..af49646b72
--- /dev/null
+++ b/src/lib/eio/eio_inline_helper.x
@@ -0,0 +1,105 @@
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#ifndef EIO_INLINE_HELPER_H__
23# define EIO_INLINE_HELPER_H__
24
25/**
26 * @addtogroup Eio_Helper
27 *
28 * @{
29 */
30
31/**