2020-01-12 13:38:54 -08:00
|
|
|
#include "e_system.h"
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *dev, *mountpoint, *cmd, *cmd2, *cmd1;
|
|
|
|
Ecore_Exe *exe;
|
|
|
|
Ecore_Event_Handler *handler;
|
|
|
|
Eina_Bool eject : 1;
|
|
|
|
Eina_Bool mount : 1;
|
|
|
|
Eina_Bool umount : 1;
|
|
|
|
Eina_Bool in_progress : 1;
|
|
|
|
} Action;
|
|
|
|
|
|
|
|
static Eina_List *_pending_actions = NULL;
|
|
|
|
|
|
|
|
static Eina_Bool _store_action_do(Action *a);
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_store_device_verify(const char *dev)
|
|
|
|
{
|
|
|
|
const char *s;
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
// not even /dev/something? no way.
|
|
|
|
if (!(!strncmp(dev, "/dev/", 5))) return EINA_FALSE;
|
|
|
|
// if it contains /.. - even tho it could be file/..name not file/../name
|
|
|
|
// it still looks suspicious enough so - no
|
|
|
|
if (strstr(dev, "/..")) return EINA_FALSE;
|
|
|
|
// any chars that cold be used in any evil ways - no way. device names
|
|
|
|
// should not have these...
|
|
|
|
for (s = dev; *s; s++)
|
|
|
|
{
|
|
|
|
if ((*s <= '*') || (*s == '`') || (*s == ';') || (*s == '<') ||
|
|
|
|
(*s == '>') || (*s == '?') || (*s >= '{') ||
|
|
|
|
((*s >= '[') && (*s <= '^')))
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
// must exist as a file - if not - nope
|
|
|
|
if (stat(dev, &st) != 0) return EINA_FALSE;
|
2020-04-22 06:53:25 -07:00
|
|
|
// XXX: must check it's a block device, that is removable etc. etc.
|
|
|
|
// XXX: for now we have no code for this so always fail until we do
|
|
|
|
return EINA_FALSE;
|
|
|
|
// return EINA_TRUE;
|
2020-01-12 13:38:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_store_uuid_verify(const char *dev)
|
|
|
|
{
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
if (!(!strncmp(dev, "UUID=", 5))) return EINA_FALSE;
|
|
|
|
for (s = dev + 5; *s; s++)
|
|
|
|
{
|
|
|
|
if ((!isalnum(*s)) && (*s != '-')) return EINA_FALSE;
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2020-05-28 03:24:32 -07:00
|
|
|
_mkdir(const char *path)
|
2020-01-12 13:38:54 -08:00
|
|
|
{
|
|
|
|
mode_t um;
|
|
|
|
int ret, e;
|
|
|
|
|
|
|
|
um = umask(0);
|
|
|
|
errno = 0;
|
|
|
|
ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
|
|
e = errno;
|
|
|
|
umask(um);
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
if (e != EEXIST)
|
|
|
|
{
|
|
|
|
ERR("Can't create mount dir [%s]\n", path);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(path, &st) == 0)
|
|
|
|
{
|
|
|
|
if (!S_ISDIR(st.st_mode))
|
|
|
|
{
|
|
|
|
ERR("Path is not a dir [%s]\n", path);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2020-05-28 03:24:32 -07:00
|
|
|
if (st.st_uid != 0) return EINA_FALSE;
|
|
|
|
if (st.st_gid != 0) return EINA_FALSE;
|
2020-01-12 13:38:54 -08:00
|
|
|
}
|
2020-05-28 03:24:32 -07:00
|
|
|
else return EINA_FALSE;
|
2020-01-12 13:38:54 -08:00
|
|
|
}
|
|
|
|
}
|
2020-05-28 03:24:32 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_store_is_triplet(const char *mnt, char *dirs[3])
|
|
|
|
{ // check that mnt is "/media/xxx/yyy" and nothing more or less. No special
|
|
|
|
// chars or escapes like \ or * oro ; or { or [ etc.
|
|
|
|
// no ../ or ./ or empty path elements. then break up the 3 elements
|
|
|
|
// into dirs[] is we return true
|
|
|
|
const char *s, *s2;
|
|
|
|
|
|
|
|
dirs[0] = NULL;
|
|
|
|
dirs[1] = NULL;
|
|
|
|
dirs[2] = NULL;
|
|
|
|
|
|
|
|
// phase one sanity check
|
|
|
|
if (!mnt) goto err;
|
|
|
|
if (mnt[0] != '/') goto err;
|
|
|
|
for (s = mnt; *s; s++)
|
2020-01-12 13:38:54 -08:00
|
|
|
{
|
2020-05-28 03:24:32 -07:00
|
|
|
if ((*s == '\\') ||
|
|
|
|
(*s == '(') || (*s == '$') || (*s <= '*') || (*s == '`') ||
|
|
|
|
(*s == ';') || (*s == '<') || (*s == '>') || (*s == '?') ||
|
|
|
|
(*s >= '{') ||
|
|
|
|
((*s >= '[') && (*s <= '^')))
|
|
|
|
goto err;
|
2020-01-12 13:38:54 -08:00
|
|
|
}
|
2020-05-28 03:24:32 -07:00
|
|
|
if ((strstr(mnt, "/..")) || (strstr(mnt, "/./")) || (strstr(mnt, "//")))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
// phase 2 - break up into 3 dir components
|
|
|
|
s = mnt + 1;
|
|
|
|
if (*s == '\0') goto err;
|
|
|
|
s2 = strchr(s, '/');
|
|
|
|
if (!s2) goto err;
|
|
|
|
dirs[0] = malloc(s2 - s + 1);
|
|
|
|
if (!dirs[0]) goto err;
|
|
|
|
memcpy(dirs[0], s, s2 - s);
|
|
|
|
dirs[0][s2 - s] = 0;
|
|
|
|
s = s2 + 1;
|
|
|
|
|
|
|
|
if (*s == '\0') goto err;
|
|
|
|
s2 = strchr(s, '/');
|
|
|
|
if (!s2) goto err;
|
|
|
|
dirs[1] = malloc(s2 - s + 1);
|
|
|
|
if (!dirs[1]) goto err;
|
|
|
|
memcpy(dirs[1], s, s2 - s);
|
|
|
|
dirs[1][s2 - s] = 0;
|
|
|
|
s = s2 + 1;
|
|
|
|
|
|
|
|
if (*s == '\0') goto err;
|
|
|
|
s2 = strchr(s, '/');
|
|
|
|
if (s2) goto err; // different - if there is another / - even trailing
|
|
|
|
for (s2 = s; *s2 != '\0'; s2++); // s2 - walk to nul byte end
|
|
|
|
dirs[1] = malloc(s2 - s + 1);
|
|
|
|
if (!dirs[1]) goto err;
|
|
|
|
memcpy(dirs[1], s, s2 - s);
|
|
|
|
dirs[1][s2 - s] = 0;
|
|
|
|
s = s2 + 1;
|
|
|
|
|
2020-01-12 13:38:54 -08:00
|
|
|
return EINA_TRUE;
|
2020-05-28 03:24:32 -07:00
|
|
|
err:
|
|
|
|
free(dirs[0]);
|
|
|
|
free(dirs[1]);
|
|
|
|
free(dirs[2]);
|
|
|
|
dirs[0] = NULL;
|
|
|
|
dirs[1] = NULL;
|
|
|
|
dirs[2] = NULL;
|
|
|
|
return EINA_FALSE;
|
2020-01-12 13:38:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_store_mount_verify(const char *mnt)
|
|
|
|
{
|
2020-05-28 03:24:32 -07:00
|
|
|
char *dirs[3] = { NULL, NULL, NULL };
|
|
|
|
char *tmp = NULL;
|
2020-01-12 13:38:54 -08:00
|
|
|
|
2020-04-22 06:11:00 -07:00
|
|
|
// XXX: we should use /run/media - possibly make this adapt
|
2020-05-28 03:24:32 -07:00
|
|
|
if (!mnt) return EINA_FALSE;
|
|
|
|
if (!(!strncmp(mnt, "/media/", 7))) goto err;
|
|
|
|
if (!_store_is_triplet(mnt, dirs)) goto err;
|
|
|
|
tmp = malloc(strlen(mnt) + 1);
|
|
|
|
if (!tmp)
|
2020-01-12 13:38:54 -08:00
|
|
|
{
|
2020-05-28 03:24:32 -07:00
|
|
|
free(dirs[0]);
|
|
|
|
free(dirs[1]);
|
|
|
|
free(dirs[2]);
|
|
|
|
return EINA_FALSE;
|
2020-01-12 13:38:54 -08:00
|
|
|
}
|
2020-05-28 03:24:32 -07:00
|
|
|
// 2nd path must be username
|
|
|
|
if (!!strcmp(dirs[1], user_name)) goto err;
|
|
|
|
|
|
|
|
tmp[0] = 0;
|
|
|
|
strcat(tmp, "/");
|
|
|
|
strcat(tmp, dirs[0]);
|
|
|
|
if (!_mkdir(tmp)) goto err;
|
|
|
|
|
|
|
|
strcat(tmp, "/");
|
|
|
|
strcat(tmp, dirs[1]);
|
|
|
|
if (!_mkdir(tmp)) goto err;
|
|
|
|
|
|
|
|
strcat(tmp, "/");
|
|
|
|
strcat(tmp, dirs[2]);
|
|
|
|
if (!_mkdir(tmp)) goto err;
|
|
|
|
|
|
|
|
free(tmp);
|
|
|
|
free(dirs[0]);
|
|
|
|
free(dirs[1]);
|
|
|
|
free(dirs[2]);
|
2020-01-12 13:38:54 -08:00
|
|
|
return EINA_TRUE;
|
|
|
|
err:
|
2020-05-28 03:24:32 -07:00
|
|
|
ERR("Malformed mount point or create error [%s]\n", mnt);
|
|
|
|
free(tmp);
|
|
|
|
free(dirs[0]);
|
|
|
|
free(dirs[1]);
|
|
|
|
free(dirs[2]);
|
2020-01-12 13:38:54 -08:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_store_umount_verify(const char *mnt)
|
|
|
|
{
|
2020-05-28 03:24:32 -07:00
|
|
|
char *dirs[3] = { NULL, NULL, NULL };
|
|
|
|
char *tmp = NULL;
|
2020-01-12 13:38:54 -08:00
|
|
|
struct stat st;
|
|
|
|
|
2020-04-22 06:11:00 -07:00
|
|
|
// XXX: we should use /run/media - possibly make this adapt
|
2020-05-28 03:24:32 -07:00
|
|
|
if (!mnt) return EINA_FALSE;
|
|
|
|
if (!(!strncmp(mnt, "/media/", 7))) goto err;
|
|
|
|
if (!_store_is_triplet(mnt, dirs)) goto err;
|
|
|
|
tmp = malloc(strlen(mnt) + 1);
|
|
|
|
if (!tmp)
|
2020-01-12 13:38:54 -08:00
|
|
|
{
|
2020-05-28 03:24:32 -07:00
|
|
|
free(dirs[0]);
|
|
|
|
free(dirs[1]);
|
|
|
|
free(dirs[2]);
|
|
|
|
return EINA_FALSE;
|
2020-01-12 13:38:54 -08:00
|
|
|
}
|
2020-05-28 03:24:32 -07:00
|
|
|
// 2nd path must be username
|
|
|
|
if (!!strcmp(dirs[1], user_name)) goto err;
|
|
|
|
if (stat(mnt, &st) != 0) goto err;
|
|
|
|
if (!S_ISDIR(st.st_mode)) goto err;
|
2020-04-22 06:11:00 -07:00
|
|
|
if (st.st_uid != 0) goto err;
|
|
|
|
if (st.st_gid != 0) goto err;
|
2020-05-28 03:24:32 -07:00
|
|
|
|
|
|
|
free(tmp);
|
|
|
|
free(dirs[0]);
|
|
|
|
free(dirs[1]);
|
|
|
|
free(dirs[2]);
|
2020-01-12 13:38:54 -08:00
|
|
|
return EINA_TRUE;
|
|
|
|
err:
|
2020-05-28 03:24:32 -07:00
|
|
|
ERR("Malformed umount point [%s]\n", mnt);
|
|
|
|
free(tmp);
|
|
|
|
free(dirs[0]);
|
|
|
|
free(dirs[1]);
|
|
|
|
free(dirs[2]);
|
2020-01-12 13:38:54 -08:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_store_action_free(Action *a)
|
|
|
|
{
|
|
|
|
free(a->dev);
|
|
|
|
free(a->mountpoint);
|
|
|
|
free(a->cmd);
|
|
|
|
free(a->cmd2);
|
|
|
|
free(a->cmd1);
|
|
|
|
if (a->handler) ecore_event_handler_del(a->handler);
|
|
|
|
if (a->exe) ecore_exe_free(a->exe);
|
|
|
|
free(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_store_pending_action_next(void)
|
|
|
|
{
|
|
|
|
while (_pending_actions)
|
|
|
|
{
|
|
|
|
Action *a = _pending_actions->data;
|
|
|
|
if (_store_action_do(a)) break;
|
|
|
|
else _pending_actions = eina_list_remove(_pending_actions, a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_cb_store_eject_exe_del(void *data, int ev_type EINA_UNUSED, void *event)
|
|
|
|
{
|
|
|
|
Ecore_Exe_Event_Del *ev = event;
|
|
|
|
Action *a = data;
|
|
|
|
|
|
|
|
if (ev->exe == a->exe)
|
|
|
|
{
|
|
|
|
a->exe = NULL;
|
|
|
|
if (a->eject)
|
|
|
|
e_system_inout_command_send("store-eject", "%i %s",
|
|
|
|
ev->exit_code, a->dev);
|
|
|
|
else if ((a->mount) &&
|
|
|
|
((ev->exit_code == 0) ||
|
|
|
|
(!((a->cmd) || (a->cmd1) || (a->cmd2)))))
|
|
|
|
e_system_inout_command_send("store-mount", "%i %s %s",
|
|
|
|
ev->exit_code, a->dev, a->mountpoint);
|
|
|
|
else if (a->umount)
|
|
|
|
{
|
|
|
|
if (ev->exit_code == 0)
|
|
|
|
{
|
|
|
|
rmdir(a->mountpoint);
|
|
|
|
}
|
|
|
|
e_system_inout_command_send("store-umount", "%i %s",
|
|
|
|
ev->exit_code, a->mountpoint);
|
|
|
|
}
|
|
|
|
if (((a->cmd) || (a->cmd1) || (a->cmd2)) && (ev->exit_code != 0))
|
|
|
|
{
|
|
|
|
if (!_store_action_do(a))
|
|
|
|
{
|
|
|
|
_pending_actions = eina_list_remove(_pending_actions, a);
|
|
|
|
_store_pending_action_next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_pending_actions = eina_list_remove(_pending_actions, a);
|
|
|
|
_store_action_free(a);
|
|
|
|
_store_pending_action_next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_store_action_do(Action *a)
|
|
|
|
{
|
|
|
|
a->handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
|
|
|
|
_cb_store_eject_exe_del, a);
|
|
|
|
if (!a->handler) _store_action_free(a);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (a->cmd2)
|
|
|
|
{
|
2020-07-14 05:31:29 -07:00
|
|
|
a->exe = e_system_run(a->cmd2);
|
2020-01-12 13:38:54 -08:00
|
|
|
free(a->cmd2);
|
|
|
|
a->cmd2 = NULL;
|
|
|
|
}
|
|
|
|
else if (a->cmd1)
|
|
|
|
{
|
2020-07-14 05:31:29 -07:00
|
|
|
a->exe = e_system_run(a->cmd1);
|
2020-01-12 13:38:54 -08:00
|
|
|
free(a->cmd1);
|
|
|
|
a->cmd1 = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-14 05:31:29 -07:00
|
|
|
a->exe = e_system_run(a->cmd);
|
2020-01-12 13:38:54 -08:00
|
|
|
free(a->cmd);
|
|
|
|
a->cmd = NULL;
|
|
|
|
}
|
|
|
|
a->in_progress = EINA_TRUE;
|
|
|
|
if (!a->exe) _store_action_free(a);
|
|
|
|
else return EINA_TRUE;
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_store_action_queue(Action *a)
|
|
|
|
{
|
|
|
|
if (_pending_actions)
|
|
|
|
_pending_actions = eina_list_append(_pending_actions, a);
|
|
|
|
else if (_store_action_do(a))
|
|
|
|
_pending_actions = eina_list_append(_pending_actions, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_store_eject(void *data EINA_UNUSED, const char *params)
|
|
|
|
{
|
|
|
|
// params:
|
|
|
|
// /dev/xxx
|
|
|
|
char cmd0[512];
|
|
|
|
char cmd[4096 + 512 + 128];
|
|
|
|
|
|
|
|
if (!_store_device_verify(params))
|
|
|
|
{
|
|
|
|
ERR("Invalid device [%s]\n", params);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#if defined (__FreeBSD__) || defined (__OpenBSD__)
|
|
|
|
// on bsd cdcontrol is the shnizzle for this
|
|
|
|
if (ecore_file_app_installed("cdcontrol"))
|
|
|
|
snprintf(cmd0, sizeof(cmd0), "cdcontrol eject");
|
|
|
|
// otherwise regular old eject will do
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
snprintf(cmd0, sizeof(cmd0), "eject");
|
|
|
|
if (snprintf(cmd, sizeof(cmd), "%s %s", cmd0, params) < (int)(sizeof(cmd) - 1))
|
|
|
|
{
|
|
|
|
Action *a = calloc(1, sizeof(Action));
|
|
|
|
if (a)
|
|
|
|
{
|
|
|
|
a->eject = EINA_TRUE;
|
|
|
|
a->dev = strdup(params);
|
|
|
|
a->cmd = strdup(cmd);
|
|
|
|
if ((!a->dev) || (!a->cmd)) _store_action_free(a);
|
|
|
|
else _store_action_queue(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_store_mount(void *data EINA_UNUSED, const char *params)
|
|
|
|
{
|
|
|
|
// params:
|
|
|
|
// /dev/sdc1 - /media/user/dir
|
|
|
|
// /dev/disk/by-uuid/d9c53a62-7fc2-4cc3-9616-4e41e065da4c - /media/user/dir
|
|
|
|
// /dev/sdb1 x /media/user/dir
|
|
|
|
// ...
|
|
|
|
// DEV ARG MNT
|
|
|
|
// ARG is - OR one or more of the below chars (-, xs, rx, ...):
|
|
|
|
// x = noexec
|
|
|
|
// r = ro
|
|
|
|
// s = sync
|
|
|
|
// d = dirsync
|
|
|
|
// l = lazytime
|
|
|
|
// a = noatime
|
|
|
|
// A = relatime
|
|
|
|
// D = diratime
|
|
|
|
char dev[1024], arg[128], mnt[4096], opt2[512], opt1[512], opt0[256], *p;
|
|
|
|
char cmd2[(4096 * 2) + 1024 + 500];
|
|
|
|
char cmd1[(4096 * 2) + 1024 + 500];
|
|
|
|
char cmd0[(4096 * 2) + 1024 + 500];
|
|
|
|
|
|
|
|
if (sscanf(params, "%1023s %127s %4095s", dev, arg, mnt) == 3)
|
|
|
|
{
|
|
|
|
char *mnt2;
|
|
|
|
|
|
|
|
if ((!_store_device_verify(dev)) && (!_store_uuid_verify(dev)))
|
|
|
|
{
|
|
|
|
ERR("Invalid device [%s]\n", dev);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!_store_mount_verify(mnt))
|
|
|
|
{
|
|
|
|
ERR("Invalid mount [%s]\n", mnt);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mnt2 = ecore_file_escape_name(mnt);
|
|
|
|
if (mnt2)
|
|
|
|
{
|
|
|
|
Eina_Bool o_noexec = EINA_FALSE;
|
|
|
|
Eina_Bool o_ro = EINA_FALSE;
|
|
|
|
Eina_Bool o_sync = EINA_FALSE;
|
|
|
|
Eina_Bool o_dirsync = EINA_FALSE;
|
|
|
|
Eina_Bool o_lazytime = EINA_FALSE;
|
|
|
|
Eina_Bool o_noatime = EINA_FALSE;
|
|
|
|
Eina_Bool o_relatime = EINA_FALSE;
|
|
|
|
Eina_Bool o_diratime = EINA_FALSE;
|
|
|
|
|
|
|
|
for (p = arg; *p; p++)
|
|
|
|
{
|
|
|
|
if ((*p) == 'x') o_noexec = EINA_TRUE;
|
|
|
|
else if ((*p) == 'r') o_ro = EINA_TRUE;
|
|
|
|
else if ((*p) == 's') o_sync = EINA_TRUE;
|
|
|
|
else if ((*p) == 'd') o_dirsync = EINA_TRUE;
|
|
|
|
else if ((*p) == 'l') o_lazytime = EINA_TRUE;
|
|
|
|
else if ((*p) == 'a') o_noatime = EINA_TRUE;
|
|
|
|
else if ((*p) == 'A') o_relatime = EINA_TRUE;
|
|
|
|
else if ((*p) == 'D') o_diratime = EINA_TRUE;
|
|
|
|
}
|
|
|
|
snprintf(opt0, sizeof(opt0),
|
|
|
|
"nosuid,nodev%s%s%s%s%s%s%s%s",
|
|
|
|
o_noexec ? ",noexec" : "",
|
|
|
|
o_ro ? ",ro" : "",
|
|
|
|
o_sync ? ",sync" : "",
|
|
|
|
o_dirsync ? ",dirsync" : "",
|
|
|
|
o_lazytime ? ",lazytime" : "",
|
|
|
|
o_noatime ? ",noatime" : "",
|
|
|
|
o_relatime ? ",relatime" : "",
|
|
|
|
o_diratime ? ",diratime" : "");
|
|
|
|
snprintf(opt2, sizeof(opt2), "%s,iocharset=utf8,uid=%i", opt0, uid);
|
|
|
|
snprintf(opt1, sizeof(opt1), "%s,iocharset=utf8", opt0);
|
|
|
|
// opt2, opt1, opt0
|
|
|
|
if ((snprintf(cmd2, sizeof(cmd2), "mount -o %s %s %s",
|
|
|
|
opt2, dev, mnt2) < (int)(sizeof(cmd2) - 1)) &&
|
|
|
|
(snprintf(cmd1, sizeof(cmd1), "mount -o %s %s %s",
|
|
|
|
opt1, dev, mnt2) < (int)(sizeof(cmd1) - 1)) &&
|
|
|
|
(snprintf(cmd0, sizeof(cmd0), "mount -o %s %s %s",
|
|
|
|
opt0, dev, mnt2) < (int)(sizeof(cmd0) - 1)))
|
|
|
|
{
|
|
|
|
Action *a = calloc(1, sizeof(Action));
|
|
|
|
if (a)
|
|
|
|
{
|
|
|
|
a->mount = EINA_TRUE;
|
|
|
|
a->dev = strdup(dev);
|
|
|
|
a->mountpoint = strdup(mnt);
|
|
|
|
a->cmd = strdup(cmd0);
|
|
|
|
a->cmd2 = strdup(cmd2);
|
|
|
|
a->cmd1 = strdup(cmd1);
|
|
|
|
if ((!a->dev) || (!a->mountpoint) ||
|
|
|
|
(!a->cmd) || (!a->cmd2) || (!a->cmd1))
|
|
|
|
_store_action_free(a);
|
|
|
|
else _store_action_queue(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(mnt2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_store_umount(void *data EINA_UNUSED, const char *params)
|
|
|
|
{
|
|
|
|
// params:
|
|
|
|
// /media/user/xxx
|
|
|
|
char cmd[4096];
|
|
|
|
|
|
|
|
if (!_store_umount_verify(params))
|
|
|
|
{
|
|
|
|
ERR("Invalid mount [%s]\n", params);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (snprintf(cmd, sizeof(cmd), "umount %s", params) < (int)(sizeof(cmd) - 1))
|
|
|
|
{
|
|
|
|
Action *a = calloc(1, sizeof(Action));
|
|
|
|
if (a)
|
|
|
|
{
|
|
|
|
a->umount = EINA_TRUE;
|
|
|
|
a->mountpoint = strdup(params);
|
|
|
|
a->cmd = strdup(cmd);
|
|
|
|
if ((!a->mountpoint) || (!a->cmd)) _store_action_free(a);
|
|
|
|
else _store_action_queue(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
e_system_storage_init(void)
|
|
|
|
{
|
|
|
|
e_system_inout_command_register("store-eject", _cb_store_eject, NULL);
|
|
|
|
e_system_inout_command_register("store-mount", _cb_store_mount, NULL);
|
|
|
|
e_system_inout_command_register("store-umount", _cb_store_umount, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
e_system_storage_shutdown(void)
|
|
|
|
{
|
|
|
|
// only shutdown things we really have to - no need to free mem etc.
|
|
|
|
}
|