You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2014 lines
61 KiB

#include "config.h"
#ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
#endif
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#elif defined __GNUC__
# define alloca __builtin_alloca
#elif defined _AIX
# define alloca __alloca
#elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
#else
# include <stddef.h>
# ifdef __cplusplus
extern "C"
# endif
void *alloca(size_t);
#endif
#include <math.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utime.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include <eina_stringshare.h>
#define E_TYPEDEFS
#include "e_fm_op.h"
#undef E_TYPEDEFS
#include "e_fm_op.h"
#define READBUFSIZE 65536
#define COPYBUFSIZE 16384
#define REMOVECHUNKSIZE 4096
#define NB_PASS 3
#define SYNC_TIME 0.5
#define SYNC_BYTES (5 * 1024 * 1024)
#define E_FREE(p) do { free(p); p = NULL; } while (0)
#define _E_FM_OP_ERROR_SEND_SCAN(_task, _e_fm_op_error_type, _fmt, ...) \
do \
{ \
int _errno = errno; \
_e_fm_op_scan_error = 1; \
_e_fm_op_send_error(_task, _e_fm_op_error_type, _fmt, __VA_ARGS__, strerror(_errno)); \
return 1; \
} \
while (0)
#define _E_FM_OP_ERROR_SEND_WORK(_task, _e_fm_op_error_type, _fmt, ...) \
do \
{ \
int _errno = errno; \
_e_fm_op_work_error = 1; \
_e_fm_op_send_error(_task, _e_fm_op_error_type, _fmt, __VA_ARGS__, strerror(_errno)); \
return 1; \
} \
while (0)
typedef struct _E_Fm_Op_Task E_Fm_Op_Task;
typedef struct _E_Fm_Op_Copy_Data E_Fm_Op_Copy_Data;
static E_Fm_Op_Task *_e_fm_op_task_new(void);
static void _e_fm_op_task_free(void *t);
static void _e_fm_op_remove_link_task(E_Fm_Op_Task *task);
static Eina_Bool _e_fm_op_stdin_data(void *data, Ecore_Fd_Handler *fd_handler);
static void _e_fm_op_set_up_idlers(void);
static void _e_fm_op_delete_idler(int *mark);
static int _e_fm_op_idler_handle_error(int *mark, Eina_List **queue, Eina_List **node, E_Fm_Op_Task *task);
static Eina_Bool _e_fm_op_work_idler(void *data);
static Eina_Bool _e_fm_op_scan_idler(void *data);
static void _e_fm_op_send_error(E_Fm_Op_Task *task, E_Fm_Op_Type type, const char *fmt, ...) EINA_PRINTF(3, 4);
static void _e_fm_op_rollback(E_Fm_Op_Task *task);
static void _e_fm_op_update_progress_report_simple(int percent, const char *src, const char *dst);
static void _e_fm_op_update_progress(E_Fm_Op_Task *task, off_t _plus_e_fm_op_done, off_t _plus_e_fm_op_total);
static void _e_fm_op_copy_stat_info(E_Fm_Op_Task *task);
static int _e_fm_op_handle_overwrite(E_Fm_Op_Task *task);
static int _e_fm_op_copy_dir(E_Fm_Op_Task *task);
static int _e_fm_op_copy_link(E_Fm_Op_Task *task);
static int _e_fm_op_copy_fifo(E_Fm_Op_Task *task);
static int _e_fm_op_open_files(E_Fm_Op_Task *task);
static int _e_fm_op_copy_chunk(E_Fm_Op_Task *task);
static int _e_fm_op_copy_atom(E_Fm_Op_Task *task);
static int _e_fm_op_scan_atom(E_Fm_Op_Task *task);
static int _e_fm_op_copy_stat_info_atom(E_Fm_Op_Task *task);
static int _e_fm_op_symlink_atom(E_Fm_Op_Task *task);
static int _e_fm_op_remove_atom(E_Fm_Op_Task *task);
static int _e_fm_op_rename_atom(E_Fm_Op_Task *task);
static int _e_fm_op_destroy_atom(E_Fm_Op_Task *task);
static void _e_fm_op_random_buf(char *buf, ssize_t len);
static void _e_fm_op_random_char(char *buf, size_t len);
static int _e_fm_op_make_copy_name(const char *abs, char *buf, size_t buf_size);
Eina_List *_e_fm_op_work_queue = NULL, *_e_fm_op_scan_queue = NULL;
Ecore_Idler *_e_fm_op_work_idler_p = NULL, *_e_fm_op_scan_idler_p = NULL;
int _e_fm_op_abort = 0; /* Abort mark. */
int _e_fm_op_scan_error = 0;
int _e_fm_op_work_error = 0;
int _e_fm_op_overwrite = 0;
int _e_fm_op_error_response = E_FM_OP_NONE;
int _e_fm_op_overwrite_response = E_FM_OP_NONE;
Eina_List *_e_fm_op_separator = NULL;
char *_e_fm_op_stdin_buffer = NULL;
double _e_fm_op_last_sync = 0.0;
unsigned long long _e_fm_op_bytes_sync = 0;
struct _E_Fm_Op_Task
{
struct
{
const char *name;
struct stat st;
} src;
struct
{
const char *name;
size_t done;
} dst;
int started, finished;
unsigned int passes;
off_t pos;
void *data;
E_Fm_Op_Task *parent;
E_Fm_Op_Type type;
E_Fm_Op_Type overwrite;
Eina_List *link;
};
struct _E_Fm_Op_Copy_Data
{
FILE *from;
FILE *to;
};
int
main(int argc, char **argv)
{
int i, last;
E_Fm_Op_Type type;
ecore_app_no_system_modules();
ecore_init();
_e_fm_op_stdin_buffer = malloc(READBUFSIZE);
if (!_e_fm_op_stdin_buffer) return 0;
ecore_main_fd_handler_add(STDIN_FILENO, ECORE_FD_READ, _e_fm_op_stdin_data,
NULL, NULL, NULL);
if (argc < 3) return 0;
last = argc - 1;
i = 2;
if (!strcmp(argv[1], "cp")) type = E_FM_OP_COPY;
else if (!strcmp(argv[1], "mv"))
type = E_FM_OP_MOVE;
else if (!strcmp(argv[1], "rm"))
type = E_FM_OP_REMOVE;
else if (!strcmp(argv[1], "srm"))
type = E_FM_OP_SECURE_REMOVE;
else if (!strcmp(argv[1], "lns"))
type = E_FM_OP_SYMLINK;
else if (!strcmp(argv[1], "mvf"))
type = E_FM_OP_RENAME;
else return 0;
if (type == E_FM_OP_SECURE_REMOVE)
{
_e_fm_op_work_queue = eina_list_append(_e_fm_op_work_queue, NULL);
_e_fm_op_separator = _e_fm_op_work_queue;
}
if ((type == E_FM_OP_COPY) ||
(type == E_FM_OP_SYMLINK) ||
(type == E_FM_OP_MOVE) ||
(type == E_FM_OP_RENAME))
{
if (argc < 4) goto quit;
if (ecore_file_is_dir(argv[last]))
{
char buf[PATH_MAX];
char *p2, *p3;
int p2_len, last_len, done, total;
p2 = ecore_file_realpath(argv[last]);
if (!p2) goto quit;
p2_len = strlen(p2);
last_len = strlen(argv[last]);
if ((last_len < 1) || (last_len + 2 >= PATH_MAX))
{
E_FREE(p2);
goto quit;
}
memcpy(buf, argv[last], last_len);
if (buf[last_len - 1] != '/')
{
buf[last_len] = '/';
last_len++;
}
p3 = buf + last_len;
done = 0;
total = last - 2;
for (; i < last; i++)
{
const char *name;
size_t name_len;
char *dir;
int r;
Eina_Bool make_copy;
/* Don't move a dir into itself */
if (ecore_file_is_dir(argv[i]) &&
(strcmp(argv[i], p2) == 0))
goto skip_arg;
make_copy = EINA_FALSE;
/* Don't move/rename/symlink into same directory
* in case of copy, make copy name automatically */
dir = ecore_file_dir_get(argv[i]);
if (dir)
{
r = (strcmp(dir, p2) == 0);
E_FREE(dir);
if (r)
{
if (type == E_FM_OP_COPY) make_copy = EINA_TRUE;
else goto skip_arg;
}
}
name = ecore_file_file_get(argv[i]);
if (!name) goto skip_arg;
name_len = strlen(name);
if (p2_len + name_len >= PATH_MAX) goto skip_arg;
memcpy(p3, name, name_len + 1);
if (make_copy)
{
if (_e_fm_op_make_copy_name(buf, p3, PATH_MAX - p2_len - 1))
goto skip_arg;
}
if ((type == E_FM_OP_SYMLINK) &&
(symlink(argv[i], buf) == 0))
{
done++;
_e_fm_op_update_progress_report_simple
(done * 100 / total, argv[i], buf);
}
else
{
if (type == E_FM_OP_MOVE)
{
if (!strcmp(argv[i], buf))
goto skip_arg;
if (buf[0] != '/')
{
free(p2);
_E_FM_OP_ERROR_SEND_SCAN(0, E_FM_OP_ERROR,
"Unknown destination '%s': %s.", buf);
}
}
else if (type == E_FM_OP_RENAME)
{
if (!strcmp(argv[i], buf))
goto skip_arg;
if (buf[0] != '/')
{
free(p2);
_E_FM_OP_ERROR_SEND_SCAN(0, E_FM_OP_ERROR,
"Unknown destination '%s': %s.", buf);
}
if (access(buf, F_OK) == -1)
{
/* race condition, i know, but it's
* unvoidable. */
if (rename(argv[i], buf) == -1)
{
/* if it's another device */
if (errno == EXDEV)
type = E_FM_OP_MOVE;
else
{
free(p2);
_E_FM_OP_ERROR_SEND_SCAN(0, E_FM_OP_ERROR,
"Cannot move '%s' to '%s': %s.",
argv[i], buf);
}
}
else
{
done++;
_e_fm_op_update_progress_report_simple
(done * 100 / total, argv[i], buf);
goto skip_arg;
}
}
else
{
/* if the destination file already exists,
* store a task which handles overwrite */
struct stat st1;
struct stat st2;
if ((stat(argv[i], &st1) == 0) &&
(stat(buf, &st2) == 0))
{
/* if files are not on the same device */
if (st1.st_dev != st2.st_dev)
type = E_FM_OP_MOVE;
}
else type = E_FM_OP_MOVE;
}
}
if (type == E_FM_OP_MOVE)
{
_e_fm_op_work_queue = eina_list_append(_e_fm_op_work_queue, NULL);
_e_fm_op_separator = _e_fm_op_work_queue;
}
E_Fm_Op_Task *task;
task = _e_fm_op_task_new();
task->type = type;
task->src.name = eina_stringshare_add(argv[i]);
task->dst.name = eina_stringshare_add(buf);
_e_fm_op_scan_queue =
eina_list_append(_e_fm_op_scan_queue, task);
}
skip_arg:
continue;
}
E_FREE(p2);
}
else if (argc == 4)
{
char *p, *p2;
p = ecore_file_realpath(argv[2]);
p2 = ecore_file_realpath(argv[3]);
/* Don't move a file on top of itself. */
i = (strcmp(p, p2) == 0);
E_FREE(p);
E_FREE(p2);
if (i) goto quit;
if ((type == E_FM_OP_SYMLINK) &&
(symlink(argv[2], argv[3]) == 0))
{
_e_fm_op_update_progress_report_simple(100, argv[2], argv[3]);
goto quit;
}
else
{
if (type == E_FM_OP_MOVE)
type = E_FM_OP_RENAME;
E_Fm_Op_Task *task;
task = _e_fm_op_task_new();
task->type = type;
task->src.name = eina_stringshare_add(argv[2]);
task->dst.name = eina_stringshare_add(argv[3]);
_e_fm_op_scan_queue = eina_list_append(_e_fm_op_scan_queue, task);
}
}
else
goto quit;
}
else if ((type == E_FM_OP_REMOVE) || (type == E_FM_OP_SECURE_REMOVE))
{
E_Fm_Op_Task *task;
while (i <= last)
{
task = _e_fm_op_task_new();
task->type = type;
task->src.name = eina_stringshare_add(argv[i]);
_e_fm_op_scan_queue = eina_list_append(_e_fm_op_scan_queue, task);
i++;
}
}
_e_fm_op_set_up_idlers();
_e_fm_op_last_sync = ecore_time_get();
ecore_main_loop_begin();
quit:
ecore_shutdown();
E_FREE(_e_fm_op_stdin_buffer);
E_FM_OP_DEBUG("Slave quit.\n");
return 0;
}
/* Create new task. */
static E_Fm_Op_Task *
_e_fm_op_task_new()
{
E_Fm_Op_Task *t;
t = malloc(sizeof(E_Fm_Op_Task));
t->src.name = NULL;
memset(&(t->src.st), 0, sizeof(struct stat));
t->dst.name = NULL;
t->dst.done = 0;
t->started = 0;
t->finished = 0;
t->data = NULL;
t->type = E_FM_OP_NONE;
t->overwrite = E_FM_OP_NONE;
t->link = NULL;
t->pos = t->passes = 0;
return t;
}
/* Free task. */
static void
_e_fm_op_task_free(void *t)
{
E_Fm_Op_Task *task = t;
E_Fm_Op_Copy_Data *data;
if (!task) return;
if (task->src.name) eina_stringshare_del(task->src.name);
if (task->dst.name) eina_stringshare_del(task->dst.name);
if (task->data)
{
data = task->data;
if (task->type == E_FM_OP_COPY)
{
if (data->from) fclose(data->from);
if (data->to) fclose(data->to);
}
E_FREE(task->data);
}
E_FREE(task);
}
/* Removes link task from work queue.
* Link task is not NULL in case of MOVE. Then two tasks are created: copy and remove.
* Remove task is a link task for the copy task. If copy task is aborted (e.g. error
Fix common misspellings Some misspellings were manually reverted since in E there are tons of .po with phrases in other languages. Other than that all the changes in the following files were reverted: * src/modules/illume/dicts/English_(US).dic * src/modules/illume-keyboard/dicts/English_(US).dic Following misspellings were fixed: acquited->acquitted adres->address adress->address alreayd->already aquire->acquire arbitarily->arbitrarily cant->can't Capetown->Cape carefull->careful causalities->casualties Celcius->Celsius certian->certain commandoes->commandos considerd->considered conveyer->conveyor dependant->dependent didnt->didn't discontentment->discontent doesnt->doesn't everytime->every exemple->example existance->existence existant->existent existince->existence Farenheit->Fahrenheit forbad->forbade funguses->fungi guage->gauge guerilla->guerrilla guerillas->guerrillas happend->happened hasnt->hasn't heros->heroes inbetween->between independant->independent inital->initial intrusted->entrusted irregardless->regardless isnt->isn't knifes->knives layed->laid loosing->losing marrage->marriage midwifes->midwives miniscule->minuscule monickers->monikers mroe->more noone->no one occured->occurred omre->more paralell->parallel payed->paid planed->planned quitted->quit quizes->quizzes seperated->separated seperate->separate shoudl->should similiar->similar simplier->simpler specifiying->specifying teh->the toke->took torpedos->torpedoes Tuscon->Tucson unecessary->unnecessary useage->usage usefull->useful useing->using waht->what wanna->want whith->with wich->which withing->within SVN revision: 52006
12 years ago
* occurred and user chooses to ignore this), then the remove task is removed from
* queue with this functions.
*/
static void
_e_fm_op_remove_link_task(E_Fm_Op_Task *task)
{
List of changes: 1. Gadcon sities: -- 'E_Gadcon_Site' enum to list all available sities, -- added 'is_site' callback for distinguish gadcon sities, -- 'e_gadcon_site_is_*' helpers written to use in gadget modules, -- gadcon config dialogs modified to show only gadgets that appropriate to selected gadcon site, -- all gadget modules updated for using new callback. When callback is not provided in module, then gadget can be used in any gadcon site. 2. Filemanager: -- added error icon to unexisting path dialog, -- added callback 'func.abort' to 'E_Fm2_Op_Registry_Entry' to specify abort operation sequence (if not provided, then operation is not cancelable), -- added parameter to 'e_fm2_op_registry_entry_add' to specify abort method on construct 'E_Fm2_Op_Registry_Entry' or make non-cancelable operation if this function is not provided, -- added 'e_fm2_operation_abort' call to cancel efm2 operation, -- added method '_e_fm2_operation_abort_internal' that represent efm2 default handler of operation cancelling, -- 'done' and 'total' fields of 'E_Fm2_Op_Registry_Entry' changed to off_t type, also all message handlers modified to work with it (to show progress for large files correctly), -- improved file operation progress processing, -- added cancel button to operation progress gadget in filemanager window, -- added delete file glyph to operation progress gadget, -- improved status message for efm2 operation progress. 3. Filemanager slave: -- fixed critical bug in message handling via stdin/stdout, -- fixed critical bug in removing task from list, -- improved 'E_FM_OP_ABORT' handling, -- fix rollback counting on moving files. 4. Fileman_opinfo module: -- a new theme writed: status string and gadget for view operation status in summary and detail modes, -- summary mode: operation glyph, state message, progressbar, abort button, -- detail mode: all for summary + from filename, to filename, -- summary/detailed button works as trigger, -- added source of module theme and used images. 4. Pathbar module: -- non-critical fix, just for safety. Also patch contains several minor updates to serve main task. SVN revision: 41224
14 years ago
E_Fm_Op_Task *ltask;
if (!task) return;
if (task->link)
{
List of changes: 1. Gadcon sities: -- 'E_Gadcon_Site' enum to list all available sities, -- added 'is_site' callback for distinguish gadcon sities, -- 'e_gadcon_site_is_*' helpers written to use in gadget modules, -- gadcon config dialogs modified to show only gadgets that appropriate to selected gadcon site, -- all gadget modules updated for using new callback. When callback is not provided in module, then gadget can be used in any gadcon site. 2. Filemanager: -- added error icon to unexisting path dialog, -- added callback 'func.abort' to 'E_Fm2_Op_Registry_Entry' to specify abort operation sequence (if not provided, then operation is not cancelable), -- added parameter to 'e_fm2_op_registry_entry_add' to specify abort method on construct 'E_Fm2_Op_Registry_Entry' or make non-cancelable operation if this function is not provided, -- added 'e_fm2_operation_abort' call to cancel efm2 operation, -- added method '_e_fm2_operation_abort_internal' that represent efm2 default handler of operation cancelling, -- 'done' and 'total' fields of 'E_Fm2_Op_Registry_Entry' changed to off_t type, also all message handlers modified to work with it (to show progress for large files correctly), -- improved file operation progress processing, -- added cancel button to operation progress gadget in filemanager window, -- added delete file glyph to operation progress gadget, -- improved status message for efm2 operation progress. 3. Filemanager slave: -- fixed critical bug in message handling via stdin/stdout, -- fixed critical bug in removing task from list, -- improved 'E_FM_OP_ABORT' handling, -- fix rollback counting on moving files. 4. Fileman_opinfo module: -- a new theme writed: status string and gadget for view operation status in summary and detail modes, -- summary mode: operation glyph, state message, progressbar, abort button, -- detail mode: all for summary + from filename, to filename, -- summary/detailed button works as trigger, -- added source of module theme and used images. 4. Pathbar module: -- non-critical fix, just for safety. Also patch contains several minor updates to serve main task. SVN revision: 41224
14 years ago
ltask = eina_list_data_get(task->link);
_e_fm_op_work_queue =
eina_list_remove_list(_e_fm_op_work_queue, task->link);
List of changes: 1. Gadcon sities: -- 'E_Gadcon_Site' enum to list all available sities, -- added 'is_site' callback for distinguish gadcon sities, -- 'e_gadcon_site_is_*' helpers written to use in gadget modules, -- gadcon config dialogs modified to show only gadgets that appropriate to selected gadcon site, -- all gadget modules updated for using new callback. When callback is not provided in module, then gadget can be used in any gadcon site. 2. Filemanager: -- added error icon to unexisting path dialog, -- added callback 'func.abort' to 'E_Fm2_Op_Registry_Entry' to specify abort operation sequence (if not provided, then operation is not cancelable), -- added parameter to 'e_fm2_op_registry_entry_add' to specify abort method on construct 'E_Fm2_Op_Registry_Entry' or make non-cancelable operation if this function is not provided, -- added 'e_fm2_operation_abort' call to cancel efm2 operation, -- added method '_e_fm2_operation_abort_internal' that represent efm2 default handler of operation cancelling, -- 'done' and 'total' fields of 'E_Fm2_Op_Registry_Entry' changed to off_t type, also all message handlers modified to work with it (to show progress for large files correctly), -- improved file operation progress processing, -- added cancel button to operation progress gadget in filemanager window, -- added delete file glyph to operation progress gadget, -- improved status message for efm2 operation progress. 3. Filemanager slave: -- fixed critical bug in message handling via stdin/stdout, -- fixed critical bug in removing task from list, -- improved 'E_FM_OP_ABORT' handling, -- fix rollback counting on moving files. 4. Fileman_opinfo module: -- a new theme writed: status string and gadget for view operation status in summary and detail modes, -- summary mode: operation glyph, state message, progressbar, abort button, -- detail mode: all for summary + from filename, to filename, -- summary/detailed button works as trigger, -- added source of module theme and used images. 4. Pathbar module: -- non-critical fix, just for safety. Also patch contains several minor updates to serve main task. SVN revision: 41224
14 years ago
_e_fm_op_task_free(ltask);
task->link = NULL;
}
}
/*
* Handles data from STDIN.
* Received data must be in this format:
* 1) (int) magic number,
* 2) (int) id,
* 3) (int) message length.
* Right now message length is always 0. Id is what matters.
*
* This function uses a couple of static variables and a global
* variable _e_fm_op_stdin_buffer to deal with a situation, when read()
* did not actually read enough data.
*/
static Eina_Bool
_e_fm_op_stdin_data(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler)
{
int fd;
static char *buf = NULL;
static int length = 0;
char *begin = NULL;
ssize_t num = 0;
int msize, identity;
fd = ecore_main_fd_handler_fd_get(fd_handler);
if (!buf)
{
buf = _e_fm_op_stdin_buffer;
length = 0;
}
num = read(fd, buf, READBUFSIZE - length);
if (num == 0)
{
E_FM_OP_DEBUG("STDIN was closed. Abort. \n");
_e_fm_op_abort = 1;
}
else if (num < 0)
{
E_FM_OP_DEBUG("Error while reading from STDIN: read returned -1. (%s) Abort. \n", strerror(errno));
_e_fm_op_abort = 1;
}
else
{
length += num;
buf = _e_fm_op_stdin_buffer;
begin = _e_fm_op_stdin_buffer;
while (length >= ((int)(3 * sizeof(int))))
{
begin = buf;
/* Check magic. */
if (*((int *)(void *)buf) != E_FM_OP_MAGIC)
{
E_FM_OP_DEBUG("Error while reading from STDIN: magic is not correct!\n");
break;
}
buf += sizeof(int);
/* Read identifying data. */
memcpy(&identity, buf, sizeof(int));
buf += sizeof(int);
/* Read message length. */
memcpy(&msize, buf, sizeof(int));
buf += sizeof(int);
if ((length - 3 * (int)sizeof(int)) < msize)
{
/* There is not enough data to read the whole message. */
break;
}
length -= (3 * sizeof(int));
/* You may want to read msize bytes of data too,
* but currently commands here do not have any data.
* msize is always 0.
*/
switch (identity)
{
case E_FM_OP_ABORT:
_e_fm_op_abort = 1;
E_FM_OP_DEBUG("Aborted.\n");
break;
case E_FM_OP_ERROR_RESPONSE_ABORT:
case E_FM_OP_ERROR_RESPONSE_IGNORE_THIS:
case E_FM_OP_ERROR_RESPONSE_IGNORE_ALL:
case E_FM_OP_ERROR_RESPONSE_RETRY:
_e_fm_op_error_response = identity;
_e_fm_op_set_up_idlers();
break;
case E_FM_OP_OVERWRITE_RESPONSE_NO:
case E_FM_OP_OVERWRITE_RESPONSE_NO_ALL:
case E_FM_OP_OVERWRITE_RESPONSE_YES:
case E_FM_OP_OVERWRITE_RESPONSE_YES_ALL:
_e_fm_op_overwrite_response = identity;
_e_fm_op_set_up_idlers();
E_FM_OP_DEBUG("Overwrite response set.\n");
break;
}
}
if (length > 0) memmove(_e_fm_op_stdin_buffer, begin, length);
buf = _e_fm_op_stdin_buffer + length;
}
return ECORE_CALLBACK_RENEW;
}
static void
_e_fm_op_set_up_idlers()
{
if (!_e_fm_op_scan_idler_p)
_e_fm_op_scan_idler_p = ecore_idler_add(_e_fm_op_scan_idler, NULL);
if (!_e_fm_op_work_idler_p)
_e_fm_op_work_idler_p = ecore_idler_add(_e_fm_op_work_idler, NULL);
}
static void
_e_fm_op_delete_idler(int *mark)
{
if (mark == &_e_fm_op_work_error)
{
ecore_idler_del(_e_fm_op_work_idler_p);
_e_fm_op_work_idler_p = NULL;
}
else
{
ecore_idler_del(_e_fm_op_scan_idler_p);
_e_fm_op_scan_idler_p = NULL;
}
}