barbieri pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=2f919345028ae54d7d8fa0b1460ab42bc929e6fd
commit 2f919345028ae54d7d8fa0b1460ab42bc929e6fd Author: Gustavo Sverzut Barbieri <[email protected]> Date: Wed Nov 23 12:10:31 2016 -0200 ecore_con: export function to create local path string. The new efl_net code won't compose any path own its own, allowing the user to connect to non-EFL systems. However we need a way to use the same path Ecore_Con_Server does, so we can reach it. Then export and use ecore_con_local_path_new() to do exactly that. --- src/lib/ecore_con/Ecore_Con.h | 40 ++++++ src/lib/ecore_con/ecore_con_local.c | 220 ++++++++++++++++-------------- src/lib/ecore_con/ecore_con_local_win32.c | 52 ++++--- 3 files changed, 184 insertions(+), 128 deletions(-) diff --git a/src/lib/ecore_con/Ecore_Con.h b/src/lib/ecore_con/Ecore_Con.h index 7ed3b48..cc2dd2b 100644 --- a/src/lib/ecore_con/Ecore_Con.h +++ b/src/lib/ecore_con/Ecore_Con.h @@ -1098,6 +1098,42 @@ EAPI void ecore_con_socks_apply_always(Ecore_Con_Socks *ecs); */ /** + * @brief Create a local path to connect the socket. + * + * In the old API, ecore_con_server_add() and + * ecore_con_server_connect() calculated a local path for connections + * using @c ECORE_CON_LOCAL_USER and @c ECORE_CON_LOCAL_SYSTEM, this + * function returns that path allocated so it can be used in + * applications that want to connect to that path without replicating + * its logic. + * + * @li If @a type is @c ECORE_CON_LOCAL_USER, the server will conect to + * the Unix socket. The path to the socket is taken from XDG_RUNTIME_DIR, + * if that is not set, then from HOME, even if this is not set, then from + * TMPDIR. If none is set, then path would be /tmp. From this path the + * function would connect to socket at "[path]/.ecore/[name]/[port]". If + * port is negetive, then to socket at "[path]/.ecore/[name]". + * @li If @a type is @c ECORE_CON_LOCAL_SYSTEM, the server will connect to + * Unix socket at "/tmp/.ecore_service|[name]|[port]". If port is negetive, + * then to Unix socket at "/tmp/.ecore_service|[name]". + * + * @param is_system If #EINA_TRUE, will be a system wide socket + * similar to @c ECORE_CON_LOCAL_SYSTEM. If #EINA_FALSE, + * then it's similar to @c ECORE_CON_LOCAL_USER. + * @param name Name to associate with the socket. It is used when + * generating the socket name of a Unix socket, + * @c NULL will not be accepted. + * @param port Number to identify socket. When a Unix socket is used, + * it becomes part of the socket name. + * + * @return NULL on failure or newly allocated path string on success, + * remember to free() it after usage. + * + * @since 1.19 + */ +EAPI char *ecore_con_local_path_new(Eina_Bool is_system, const char *name, int port) EINA_WARN_UNUSED_RESULT EINA_MALLOC EINA_ARG_NONNULL(2); + +/** * @brief Create a server to listen for connections. * * @param type The connection type. @@ -1132,6 +1168,8 @@ EAPI void ecore_con_socks_apply_always(Ecore_Con_Socks *ecs); * * The @p data parameter can be fetched later using ecore_con_server_data_get() * or changed with ecore_con_server_data_set(). + * + * @see ecore_con_local_path_new() */ EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type, const char *name, int port, @@ -1182,6 +1220,8 @@ EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type, * * The @p data parameter can be fetched later using ecore_con_server_data_get() * or changed with ecore_con_server_data_set(). + * + * @see ecore_con_local_path_new() */ EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type, const char *name, int port, diff --git a/src/lib/ecore_con/ecore_con_local.c b/src/lib/ecore_con/ecore_con_local.c index 546b6e0..3bf9b97 100644 --- a/src/lib/ecore_con/ecore_con_local.c +++ b/src/lib/ecore_con/ecore_con_local.c @@ -64,24 +64,15 @@ ecore_con_local_shutdown(void) return _ecore_con_local_init_count; } -int -ecore_con_local_connect(Ecore_Con_Server *obj, - Eina_Bool (*cb_done)(void *data, Ecore_Fd_Handler *fd_handler), - void *data EINA_UNUSED) +EAPI char * +ecore_con_local_path_new(Eina_Bool is_system, const char *name, int port) { -#ifndef HAVE_LOCAL_SOCKETS - return 0; -#else - Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS); char buf[4096]; - struct sockaddr_un socket_unix; - int curstate = 0; const char *homedir; - int socket_unix_len; - buf[0] = '\0'; + EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); - if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) + if (!is_system) { #if defined(HAVE_GETUID) && defined(HAVE_GETEUID) if (getuid() == geteuid()) @@ -97,50 +88,78 @@ ecore_con_local_connect(Ecore_Con_Server *obj, } #endif - if (svr->port < 0) + if (port < 0) snprintf(buf, sizeof(buf), "%s/.ecore/%s", - homedir, svr->name); + homedir, name); else snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", - homedir, svr->name, svr->port); + homedir, name, port); + return strdup(buf); } - else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM) + else { - if (svr->port < 0) + if (port < 0) { - if (svr->name[0] == '/') - { - strncpy(buf, svr->name, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; - } + if (name[0] == '/') + return strdup(name); else { homedir = eina_environment_tmp_get(); snprintf(buf, sizeof(buf), "%s/.ecore_service|%s", - homedir, svr->name); + homedir, name); + return strdup(buf); } } else { - if (svr->name[0] == '/') - snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port); + if (name[0] == '/') + snprintf(buf, sizeof(buf), "%s|%i", name, port); else { homedir = eina_environment_tmp_get(); snprintf(buf, sizeof(buf), "%s/.ecore_service|%s|%i", - homedir, svr->name, svr->port); + homedir, name, port); } + return strdup(buf); } } +} + +int +ecore_con_local_connect(Ecore_Con_Server *obj, + Eina_Bool (*cb_done)(void *data, Ecore_Fd_Handler *fd_handler), + void *data EINA_UNUSED) +{ +#ifndef HAVE_LOCAL_SOCKETS + return 0; +#else + Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS); + char *buf = NULL; + struct sockaddr_un socket_unix; + int curstate = 0; + int socket_unix_len; + + if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) + { + buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port); + } + else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM) + { + buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port); + } else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT) { - strncpy(buf, svr->name, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; + buf = strdup(svr->name); } + EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0); + svr->fd = socket(AF_UNIX, SOCK_STREAM, 0); if (svr->fd < 0) - return 0; + { + free(buf); + return 0; + } if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; @@ -182,9 +201,8 @@ ecore_con_local_connect(Ecore_Con_Server *obj, goto error; } - svr->path = strdup(buf); - if (!svr->path) - goto error; + svr->path = buf; + buf = NULL; if (svr->type & ECORE_CON_SSL) { @@ -199,14 +217,65 @@ ecore_con_local_connect(Ecore_Con_Server *obj, if (!svr->delete_me) ecore_con_event_server_add(obj); + free(buf); + return 1; error: if (svr->fd) close(svr->fd); svr->fd = -1; + free(buf); return 0; #endif } +#ifdef HAVE_LOCAL_SOCKETS +static void +_ecore_con_local_mkpath(const char *path, mode_t mode) +{ + char *s, *d, *itr; + + if (!path) return; + EINA_SAFETY_ON_TRUE_RETURN(path[0] != '/'); + + s = strdup(path); + EINA_SAFETY_ON_NULL_RETURN(s); + d = dirname(s); + EINA_SAFETY_ON_NULL_RETURN(d); + + for (itr = d + 1; *itr != '\0'; itr++) + { + if (*itr == '/') + { + *itr = '\0'; + if (mkdir(d, mode) != 0) + { + if (errno != EEXIST) + { + ERR("could not create parent directory '%s' of path '%s': %s", d, path, strerror(errno)); + goto end; + } + } + *itr = '/'; + } + } + + if (mkdir(d, mode) != 0) + { + if (errno != EEXIST) + ERR("could not create parent directory '%s' of path '%s': %s", d, path, strerror(errno)); + else + { + struct stat st; + if ((stat(d, &st) != 0) || (!S_ISDIR(st.st_mode))) + ERR("could not create parent directory '%s' of path '%s': exists but is not a directory", d, path); + } + } + + end: + free(s); +} +#endif + int ecore_con_local_listen( Ecore_Con_Server *obj, @@ -219,11 +288,10 @@ ecore_con_local_listen( { #ifdef HAVE_LOCAL_SOCKETS Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS); - char buf[4096]; + char *buf = NULL; struct sockaddr_un socket_unix; struct linger lin; mode_t pmode; - const char *homedir; mode_t mask; int socket_unix_len; Eina_Bool abstract_socket; @@ -232,87 +300,25 @@ ecore_con_local_listen( if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) { -#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) - if (getuid() == geteuid()) -#endif - homedir = _ecore_con_local_path_get(); + buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port); -#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) - else - { - struct passwd *pw = getpwent(); - - if ((!pw) || (!pw->pw_dir)) homedir = "/tmp"; - else homedir = pw->pw_dir; - } -#endif mask = S_IRUSR | S_IWUSR | S_IXUSR; - snprintf(buf, sizeof(buf), "%s/.ecore", homedir); - if (mkdir(buf, mask) < 0) - { - if (errno != EEXIST) - { - ERR("mkdir '%s' failed", buf); - } - } - - snprintf(buf, sizeof(buf), "%s/.ecore/%s", homedir, svr->name); - if (mkdir(buf, mask) < 0) - { - if (errno != EEXIST) - { - ERR("mkdir '%s' failed", buf); - } - } - - if (svr->port < 0) - snprintf(buf, sizeof(buf), "%s/.ecore/%s", - homedir, svr->name); - else - snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", - homedir, svr->name, svr->port); + _ecore_con_local_mkpath(buf, mask); mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH; } else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM) { mask = 0; - if (svr->port < 0) - { - if (svr->name[0] == '/') - { - strncpy(buf, svr->name, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; - } - else - { - homedir = eina_environment_tmp_get(); - snprintf(buf, sizeof(buf), "%s/.ecore_service|%s", - homedir, svr->name); - } - } - else - { - if (svr->name[0] == '/') - snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port); - else - { - homedir = eina_environment_tmp_get(); - snprintf(buf, sizeof(buf), "%s/.ecore_service|%s|%i", - homedir, svr->name, svr->port); - } - } + buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port); } else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT) { - strncpy(buf, svr->name, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; - } - else - { - buf[0] = '\0'; + buf = strdup(svr->name); } + EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0); + pmode = umask(mask); start: socket_unix.sun_family = AF_UNIX; @@ -408,9 +414,8 @@ start: #ifdef HAVE_SYSTEMD fd_ready: #endif - svr->path = strdup(buf); - if (!svr->path) - goto error_umask; + svr->path = buf; + buf = NULL; svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ, @@ -419,6 +424,8 @@ fd_ready: if (!svr->fd_handler) goto error; + free(buf); + return 1; error_fd: @@ -427,6 +434,7 @@ error_fd: error_umask: umask(pmode); error: + free(buf); #endif /* HAVE_LOCAL_SOCKETS */ return 0; } diff --git a/src/lib/ecore_con/ecore_con_local_win32.c b/src/lib/ecore_con/ecore_con_local_win32.c index 09aa566..b322d9a 100644 --- a/src/lib/ecore_con/ecore_con_local_win32.c +++ b/src/lib/ecore_con/ecore_con_local_win32.c @@ -386,11 +386,29 @@ _ecore_con_local_win32_listening(void *data) return 0; } +EAPI char * +ecore_con_local_path_new(Eina_Bool is_system, const char *name, int port) +{ + char buf[256]; + + if (!is_system) + snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s%ld", name, GetProcessId(GetCurrentProcess())); + else + { + const char *computername; + + computername = getenv("COMPUTERNAME"); + snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s%ld", computername, name, GetProcessId(GetCurrentProcess())); + } + + return strdup(buf); + (void)port; // CHECK-ME: shouldn't we use port to be similar to UNIX? +} + Eina_Bool ecore_con_local_listen(Ecore_Con_Server *obj) { Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS); - char buf[256]; HANDLE thread_listening; Ecore_Win32_Handler *handler; @@ -401,16 +419,10 @@ ecore_con_local_listen(Ecore_Con_Server *obj) } if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) - snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s%ld", svr->name, GetProcessId(GetCurrentProcess())); + svr->path = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port); else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM) - { - const char *computername; - - computername = getenv("COMPUTERNAME"); - snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s%ld", computername, svr->name, GetProcessId(GetCurrentProcess())); - } + svr->path = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port); - svr->path = strdup(buf); if (!svr->path) { ERR("Allocation failed"); @@ -540,7 +552,7 @@ ecore_con_local_connect(Ecore_Con_Server *obj, { #warning "I am pretty sure cb_done should be used." Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS); - char buf[256]; + char buf = NULL; Ecore_Win32_Handler *handler_read; Ecore_Win32_Handler *handler_peek; @@ -551,14 +563,11 @@ ecore_con_local_connect(Ecore_Con_Server *obj, } if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) - snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name); + buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port); else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM) - { - const char *computername; + buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port); - computername = getenv("COMPUTERNAME"); - snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, svr->name); - } + EINA_SAFETY_ON_NULL_RETURN_VAL(buf, EINA_FALSE); while (1) { @@ -576,6 +585,7 @@ ecore_con_local_connect(Ecore_Con_Server *obj, if (GetLastError() != ERROR_PIPE_BUSY) { DBG("Connection to a server failed"); + free(buf); return EINA_FALSE; } @@ -587,12 +597,8 @@ ecore_con_local_connect(Ecore_Con_Server *obj, } } - svr->path = strdup(buf); - if (!svr->path) - { - ERR("Allocation failed"); - goto close_pipe; - } + svr->path = buf; + buf = NULL; svr->event_read = CreateEvent(NULL, TRUE, FALSE, NULL); if (!svr->event_read) @@ -636,6 +642,7 @@ ecore_con_local_connect(Ecore_Con_Server *obj, if (!svr->delete_me) ecore_con_event_server_add(obj); ResumeThread(svr->thread_read); + free(buf); return EINA_TRUE; @@ -652,6 +659,7 @@ free_path: svr->path = NULL; close_pipe: CloseHandle(svr->pipe); + free(buf); return EINA_FALSE; } --
